Simple Combinational Circuit Design

Vivado Project 4: Majority of Five

Introduction

Say you have a voting system with 5 voters. Say they won if a majority of the voters voted yes. How could you find out if there was a majority win? The logic is fairly simple and will be used in this project. Any time there are three or more of the five who vote yes, then there is a majority and the LED needs to turn on.

Before you begin, you should:
  • Have the Xilinx® Vivado WebPACK™ installed.
  • Have your FPGA board set up.
  • Be able to define a logic circuit using a truth table.
  • Be able to derive a logic equation from a truth table.
  • Be able to describe logic functions using Verilog HDL and implement them on an FPGA.
After you're done, you should:
  • Understand and be able to use Boolean Algebra.
  • Know how to create a K-Map from a truth table.
  • Know how to create minimized logic equation using K-map.
  • Know how to run a Verilog Circuit Simulation.

Inventory:

Qty Description
1 Digilent® Nexys™4, or Basys™3 FPGA Board
1 Xilinx Vivado Design Suite: WebPACK (2014.4 Recommended)

Background Knowledge

If a truth table is completed for the logic equation, it is a fairly easy step to get a maxterm equation and simplify it with an entered variable K-map. Knowing how to use and read a K-map is a fundamental step in creating a digital circuit with minimum transistors and no redundancies.

Step 1: Define Top Module and I/Os

Start a new project as instructed in previous projects. Use a blank Verilog file and construct a proper XDC file for your board.
For this project, we are going to utilize 5 inputs and an LED as an output. The LED will illuminate whenever the majority of voters vote yes.

An example of the module and I/O declaration for Verilog file is shown as follows:

				module top(
					input [4:0] sw,
					output led
				);
			

Step 2: Construct a Minimum Logic Expression From the Truth Table Using K-Map

  1. Assume that there are 5 people (A, B, C, D, and E). If three or more of them vote yes, represented by a “1”, the result is 1. Using this information, fill in a K-map to represent the logic expression. It should result in a super K-map as displayed in Fig. 1 below. The K-map below is not exactly the same as the one you will get for the majority of 5 problem.
    Figure 1. Truth table presented in a super K-Map.
  2. It is pretty difficult to loop a super K-map, so we need to compress it in order to make looping plausible.
    Figure 2. Compress the super K-Map with entered variables.
  3. Now that the K-map has been compressed, it is time to loop it. There is only one variable E here, so we consider loops with the entered variable E first. You can compare your loop result to the graph below in Fig. 3. You should have six loops to correspond to the six product terms.
    Figure 3. SOP loops with entered variable E.
  4. Now that we have covered the cells with variable E, it is time to see if all of the information in the K-map is looped. By looking at the K-map, we can see that there are a few more loops that we need to create. The column partition of the cell with the value '1' is not covered by a loop in the previous step. In order to create a fully looped K-map these cells need to be looped. You may check your loops with the graph below in Fig. 4. There should be 4 loops corresponding with the 4 product terms.
    Figure 4. SOP loops with the value 1.
  5. From the logic diagram that you have created it is now possible to construct the logic expression in SOP form as follows: \[\begin{align} Y=& A\cdot B\cdot C + A\cdot B\cdot D +A\cdot C\cdot D +B\cdot C\cdot D + A\cdot B\cdot E + A\cdot D\cdot E + \\ & A\cdot C\cdot E +B\cdot C\cdot E + C\cdot D\cdot E +B\cdot D\cdot E \end{align}\]
  6. From this SOP equation you can build a simple assign statement to control the LED wire. The following code uses “&” as the symbol for logic AND and “|” as the symbol for logic OR. This uses “assign” statements, which were discussed in-depth in prior projects. The “assign” statement and the LED will be held at logic high whenever the combinational logic statement is true.
    				assign led = (sw[0] & sw[1] & sw[2]) | //ABC
    							 (sw[0] & sw[1] & sw[3]) | //ABD
    							 (sw[0] & sw[2] & sw[3]) | //ACD
    							 (sw[1] & sw[2] & sw[3]) | //BCD
    							 (sw[0] & sw[1] & sw[4]) | //ABE
    							 (sw[0] & sw[3] & sw[4]) | //ADE
    							 (sw[0] & sw[2] & sw[4]) | //ACE
    							 (sw[1] & sw[2] & sw[4]) | //BCE
    							 (sw[2] & sw[3] & sw[4]) | //CDE
    							 (sw[1] & sw[3] & sw[4]);  //BDE
    				
  7. Finally, make sure that the module is closed with “endmodule”.
    			 		endmodule
    				

Step 3: Verify the Circuit in Simulator

How can we tell if a complex logic block is working as expected?

The Verilog code can be simulated by utilizing a Verilog test fixture, also called a test bench. To add a test fixture, you will need to right click on Simulation Sources and click Edit Simulation Sets.

When the window opens click Create file, and name the file majority_of_five_test_fixture.

Once the file is created it will be under the Simulation Sources section of the project manager sources tab. Expand this section and double click the file you just created. The file will contain a template for a module. You can delete everything in this file, we will write the test fixture ourselves.

The first line of the test fixture should contain the timescale. You may recognize this line from the other Verilog files we created.

			'timescale 1ns/ 1ps
			

The 'timescale compiler directive defines the units used in a delay command, which is simply “#50”. This means that there is a delay for 50 units defined in the 'timescale compiler directive. The value before the backslash is the delay unit and the value after the backslash defines the smallest increment that can be used in the delay.

The test fixture block of code is a module just like a typical Verilog module but functioning in test fixture, we artificially manipulate the inputs and can examine how the circuit behaves in simulation.

  1. Declare a test bench.

    I named the test bench to match the simulation file we created. The next two lines define the inputs and outputs we are interested in testing. Unlike the circuit that was built as a Verilog Module, a test bench is a module that has no input or output ports. It only has internal signals that are connected to the circuit under test (CUT). It generates inputs for the CUT and senses the outputs of the CUT to verify that the CUT is implemented as specified.

    						module majority_of_five_test_fixture;
    						
    						// Inputs
    						reg [4:0] sw;
    						// Outputs
    						wire led;
    					
  2. Instantiate the “majority of five” in the test bench.

    Next we need to instantiate the module that we are testing. The majorityof5 module is instantiated in the test fixture. The input port “sw” of the top module is connected to an internal register called sw as declared in the previous step, the output port LED is connected to the wired LED. Later projects will go into further detail on instantiating.

    						// Instantiate the Unit Under Test (UUT)
    						majorityof5 uut (
    							.sw(sw),
    							.led(led)
    						);
    					
  3. Generating the stimulus in the test bench.

    In this part of the project, you will start writing codes to generate stimulus for the “majority of five” circuit. Initial block is used here to code the stimulus generation. Initial block will be processed only once by the simulator. Before the initial block, we will define an integer k, so that we can loop through all the possible input combinations for the “majority of five” circuit. Inside the initial block, we will initialize all the input to zero. A for statement is used to loop through all the input possibilities. One input pattern will be held at the input for 20 ns before updating to the next input pattern. After cycling through all of the possible input patterns, the $finish command is used to end the simulation. The code is shown as follows:

    						// Declare loop index variable
    						integer k;
    						
    						// Apply input stimulus
    						initial
    						begin
    							sw = 0;
    						
    							for (k=0; k<32; k=k+1)
    								#20 sw = k;
    						
    							#20	$finish;
    						end
    					
  4. Finish the fixture.

    Finally, we close the module as usual with endmodule.

    						endmodule
    					
  5. So the test bench should look like the following:
    						'timescale 1ns/ 1ps
    
    						module testbench;
    						
    						// Inputs
    						reg [4:0] sw;
    						// Outputs
    						wire led;
    						
    						// Instantiate the Unit Under Test (UUT)
    						top uut (
    							.sw(sw),
    							.led(led)
    						);
    
    						// Declare loop index variable
    						integer k;
    						
    						// Apply input stimulus
    						initial
    						begin
    							sw = 0;
    						
    							for (k=0; k<32; k=k+1)
    								#20 sw = k;
    						
    							#20	$finish;
    						end
    						
    						endmodule
    					
  6. Now that the code is done, it is time to simulate. In the flow navigator on the left hand side of the window, under the Simulation heading click Run Simulation and select Run Behavioral Simulation.
  7. After the simulation runs, the Behavioral Simulation window will appear, but it may not open. Select the tab with an untitled name. Your simulation should look like the image below.
  8. In order to see the full simulation shown in the image below, you will need to click Zoom fit. Zoom fit is the icon of the magnifying glass with the square around it.

    Expand the sw section and you will be able to see the changing values as waveforms.

    You can also put down a cursor, the yellow line, and this will show the current values. Notice where I have the cursor in the image below: sw 4 through 2 are high, so led is high. Also notice that led is held high anytime three or more switches are high. You have now successfully run a Verilog Simulation for Majority of Five!

Test Your Knowledge!

Now that you've completed this project, try these modifications:

  • Come up with a POS equation by looping the K-Map again and simulate the POS circuit.
  • Try to code the logic expression in an un-optimized fashion (same as we did in previous projects). Use View RTL Schematic / Technology Schematic under Synthesize Step in Implementation View to see how the tools optimize the function. Is it the same as what we did by hand?

Challenge Problem

  • If you are confident in your understanding of the majority of five, go ahead and try out the design challenge problem below for some extra practice!

  • Other product and company names mentioned herein are trademarks or trade names of their respective companies. © 2014 Digilent Inc. All rights reserved.