November 17

Building Digital Circuits with VHDL – Part 2

0  comments

This is the second part of our VHDL tutorial, where I'll show you how to implement combinational circuits.

If you haven’t yet watched the first part, I highly recommend you pause this video right now and go through that one first, since understanding the concepts in this lesson relies heavily on what we covered previously.

More...

Key Concepts from the Previous Video

Let me first remind you about what we discussed in the previous video.

We discussed how logic circuits can be divided into two main categories: combinational and sequential circuits.

With hardware description languages like VHDL, you can describe and implement either type of logic circuit.

In VHDL, you can describe combinational circuits in the Concurrent section, while sequential circuits are described in the Process statement.

Designing Combinational Circuits in VHDL

In today’s lesson, I’ll focus on designing and describing combinational logic circuits using VHDL.

In the Concurrent section, VHDL provides two signal assignment statements to describe combinational circuits: One is called Selected Signal Assignment and the other is Conditional Signal Assignment.

In this video, I’ll focus on the Selected Signal Assignment.

To illustrate this, I’ve prepared an example so you can understand how Selected Signal Assignment works by implementing a simple design. 

Implementing a 4-To-1 Multiplexer in VHDL

You probably remember the multiplexer block from your logic circuits course – it’s a type of combinational circuit in digital logic. 

Multiplexers have several input signals, one output signal, and a set of control or select lines. 

Based on the value in the control lines, one of the input signals is connected to the output. For instance, in the 4-to-1 multiplexer shown in the figure below, we have four inputs, labeled ABC, and D, and one output labeled F.

4-to-1-Multiplexer

4-To-1 Multiplexer.

Since we have four inputs, we need two control inputs or select lines, which we’ll call S0 and S1

Depending on the binary value of these control inputs, one of the inputs connects to the output.

The-truth-table-for-a-4-to1-multiplexer.

The truth table for a 4-to1 multiplexer.

In the truth table for this multiplexer, you can see that when S0 and S1 are both zero, input A is routed to output F

When the control input value is 1, input B goes to F

When it’s 2, input C connects to F

And when it’s 3, input D connects to F.

Selected Signal Assignment Code for Multiplexer

Now, let’s see how we can describe this multiplexer in VHDL using the Selected Signal Assignment construct.

As I explained in previous videos, in VHDL, we use two main parts to define a module: The first part is the Entity, where we specify input and output ports. The second part is the Architecture, where we describe the actual circuit.

There's also an initial section where we include the IEEE library.

This library contains the standard definitions and constructs used in VHDL coding, so it’s essential to start every VHDL code with this line:

Library IEEE;  

This loads the IEEE library, which itself is made up of several packages, some of which are very commonly used.

One of these packages that you must always call at the beginning of your code is the STD_Logic_1164 package. 

use IEEE.STD_LOGIC_1164.ALL; 

To include it, use the keyword use, followed by the library name (IEEE), a dot, and then the package name. To access all the features of this package, end the line with All.

Library IEEE;
use IEEE.STD_LOGIC_1164.ALL; 

To describe the multiplexer, as I mentioned, the first step is to define the inputs and outputs using the Entity section.

Since this is a 4-to-1 multiplexer, we define four inputs: A, B, C, and D. Here, we set their mode to input and their type to STD_Logic.

entity MUX4to1 is
		Port (
							A   : in  STD_LOGIC;
							B   : in  STD_LOGIC;
							C   : in  STD_LOGIC;
							D   : in  STD_LOGIC;
							s   : in  STD_LOGIC_VECTOR (1 downto 0);
							f   : out STD_LOGIC
					);
end MUX4to1;

For the output, which we’ll name F, we set its mode to output and, since it’s a single-bit signal, we use STD_Logic as well.

Now, regarding the control signal S, since it's a two-bit signal, we have two options.

One is to define two single-bit signals using STD_Logic type. 

The second approach is what you see in this code. Instead of using two single-bit signals, I'm using one two-bit signal.

To define a two-bit signal, we use a type called STD_Logic_Vector. STD_Logic_Vector is used whenever we need to define signals with more than one bit.

To declare such a signal, we write STD_Logic_Vector and specify the bit width.

For instance, since we need a two-bit signal here, we define it as:

 
s   : in  STD_LOGIC_VECTOR (1 downto 0);

This line means we’re creating a two-bit signal with indices 1 and 0.

Now, as I mentioned, to define a 4-to-1 multiplexer with the Selected Signal Assignment statement, we use a specific format, as shown in the code. 

 
with S select 
			F			<=     A when "00",
										B when "00",
										C when "00",
										D when others;

This statement begins with the keyword with, followed by the signal we want to base our conditions on – in our case, this is the signal S. Next, we use the keyword select.

Next, we specify that signal A should be assigned to signal F when "00". What does "00" mean here?

It means when the condition signal, which is S in this example, equals "00" - in other words, when the control input S is "00", input A should be assigned to output F

Next, we assign B to F when "01," meaning that when S equals "01", input B is passed to the output. 

Then we assign C to F when “10”. 

And finally, we specify that D should be assigned to F for any other values of S using the term when others. When others covers all the remaining cases.

Once we’ve written the code, we can check it for syntax errors to ensure everything is correct. To do this, simply click on the code file and, at the bottom, in the Processes section, double-click on Check Syntax.

Check Syntax

We can check the code for syntax errors to ensure everything is correct.

The ISE software will then analyze the code to confirm that there are no syntax issues.

If the syntax check completes successfully, you’ll see a message that says "Syntax check completed successfully."

Successful Syntax Check

If the syntax check completes successfully, you’ll see a message that says "Syntax check completed successfully."

If there’s an error, it will be displayed at the bottom of the screen, allowing you to review each error one by one and see how to resolve them.

To help you become more familiar with the Selected Signal Assignment statement and learn some additional coding tips along the way, let's modify our multiplexer example a bit.

Modifying the Multiplexer With an Enable Signal

In this version, in addition to the control inputs S0 and S1, we'll add a new control input called Enable signal, which we'll denote as En in the code. 

4-to-1-Multiplexer-Enable

4-To-1 Multiplexer with enable signal.

According to the truth table, if the Enable signal (En) is set to 1, the multiplexer functions as before: that is, based on the value of S, one of the inputs A through D is connected to the output.

The-truth-table-for-a-4-To-1-multiplexer-with-enable-signal.

The truth table for a 4-To-1 multiplexer with enable signal. 

But if Enable is 0, regardless of the values of S0 and S1, the output signal is set to 0.

VHDL Code for the Multiplexer with an Enable Signal

Now, let’s see how we can implement this circuit using the Selected Signal Assignment construct.

 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

entity Example_03_With_Select_MUX4to1 is

	port
			(
				A       :  in    std_logic;
				B       :  in    std_logic;
				C       :  in    std_logic;
				D       :  in    std_logic;
				S       :  in    std_logic_vector(1 downto 0);
				En      :  in    std_logic;
				F       :  out   std_logic
			);
end Example_03_With_Select_MUX4to1;

architecture Behavioral of Example_03_With_Select_MUX4to1 is

	signal  SEn  :  std_logic_vector(2 downto 0) := (others=>'0');

begin

	SEn    <=  S & En;
						
	with SEn select
			 f  <=  A      when "001",
							B      when "011",
							C      when "101",
							D      when "111",
						 '0'     when others;

end Behavioral;

The first part of the code, the Entity section, doesn’t change much except that we now add the Enable signal. 

This signal is a single bit, so we define it with the type STD_Logic.

The main difference in this code compared to the previous one is that for selecting the output signal, we now need both the S signal and the Enable signal to work together.

However, the Selected Signal Assignment only allows one signal to be used for selection. So, what do you think is the solution?

To address this, you can define an internal signal and assign both S and En signals to it, then use that signal as the select signal in the Selected Signal Assignment.

To do this, we need to introduce a new operator.

Before diving into the code, let me explain this operator. 

Introduction to Concatenation Operator (&)

In VHDL, there’s a very useful operator called the Concatenation operator, represented by the ampersand symbol (&.)

To get familiar with this operator, imagine we’ve defined two signals, A and B. Signal A is 3 bits wide, and signal B is 5 bits wide.

To explain this example clearly, we've labeled the bits of signal A as A0, A1, and A2, and the bits of signal B as B0 through B4.

If we use the assignment `C <= A & B;`, the value assigned to signal C will be the combination of B0 through B4 followed by A0 through A2.

In other words, signals A and B are concatenated into signal C.

When using this concatenation, you must ensure that the width of the signal on the left side of the assignment (in this case, C) matches the total width of the signals being combined on the right. 

So, if A is three bits wide and B is five bits, C needs to be eight bits wide.

By using the concatenation operator, you can combine multiple signals and assign them to a new signal.

Applying the Concatenation Operator to the Construct

Now, let’s apply this concept to combine the two control signals, S and Enable, into a signal that we can use in the Selected Signal Assignment construct.

To do this, we first define an internal signal within the FPGA.

In VHDL, as I mentioned in the previous tutorial, we define signals in the declarative region which is the area between the keyword Architecture and the keyword Begin. This is where we can declare signals and modules.

To declare this internal signal, we use the keyword Signal, followed by the signal name, which we’ll call SEn since it will combine the signals S and Enable. After a colon, we specify the signal type.

 
signal   SEn  :  std_logic_vector(2 downto 0) := (others=>'0');

Since we’re combining a single-bit signal (Enable) with a two-bit signal (S), we end up with a three-bit signal.

So we use the type STD_Logic_Vector and define the width as three bits, from 2 downto 0.

When defining a signal, you can also assign it an initial value.

To do this, use the symbol := and specify the initial value in quotation marks. Here, we’ll set the initial value of the signal to '0'.

After the Begin keyword in the Architecture section – where we describe the circuit in the concurrent section – we concatenate the Enable signal and the S signal using the concatenation operator and assign the result to the internal signal SEn.

 
SEn    <=  S & En;

This makes SEn a three-bit signal, where the least significant bit is Enable and the two most significant bits are S.

Now, in the Selected Signal Assignment construct, which, as I mentioned, can only have one condition signal, I can use signal SEn, knowing that SEn effectively incorporates both S and Enable.

Now, to rewrite the conditions, we specify that input A is assigned to F when "001" – meaning if SEn is equal to "001".

You know that the least significant bit corresponds to Enable – so it means that if Enable equals one, and if S equals "00", assign A to the output.

If Enable is 1 and S is "01", B is assigned to F, and so on, until we reach the condition where Enable is 1 and S is "11", which would assign D to F.

 
with SEn select
				 f  <=  A     when "001",
								B     when "011",
								C     when "101",
								D     when "111",
							 '0'    when others;

So, we covered all possible cases where En equals 1.

For other cases – that is, when Enable is 0 – the value of the control signal S doesn't matter to us. So, we write when others, meaning when Enable equals 0, assign a value of 0 to the output.

We are doing this according to the definition we had for the Enable control input in our 4-to-1 multiplexer. 

Keep in mind that when you're assigning a value to a signal, if it's a single-bit value, you enclose it in single quotation marks (' '), and if it's a multi-bit value, you enclose it in double quotation marks (" ").

So, this is how we described the code for a 4-to-1 multiplexer with an Enable input signal using VHDL.

In upcoming tutorials, I’ll introduce additional constructs in VHDL that allow us to describe other types of digital circuits. 

Did you find the tutorial "Building Digital Circuits with VHDL – Part 2" helpful?

If you have any questions about this post, please feel free to ask in the comments section below. And if you enjoyed the content, don't forget to share it with your friends!

About the author 

Ahmad Saghafi

Hi, I’m Ahmad, founder of FPGATEK and creator of the FPGA Design Blueprint training. With over 15 years of hands-on experience and a wealth of knowledge from successfully implementing numerous industrial projects, I am thrilled to share my insights and expertise with you on this website.

Enjoyed this article?


You may also like:

Leave a Comment

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Get Started With FPGA In 20 Minutes

>