VHDL Logical Operators and Signal Assignments for Combinational Logic
In this post, we discuss the VHDL logical operators, when-else statements , with-select statements and instantiation . These basic techniques allow us to model simple digital circuits.
In a previous post in this series, we looked at the way we use the VHDL entity, architecture and library keywords. These are important concepts which provide structure to our code and allow us to define the inputs and outputs of a component.
However, we can't do anything more than define inputs and outputs using this technique. In order to model digital circuits in VHDL, we need to take a closer look at the syntax of the language.
There are two main classes of digital circuit we can model in VHDL – combinational and sequential .
Combinational logic is the simplest of the two, consisting primarily of basic logic gates , such as ANDs, ORs and NOTs. When the circuit input changes, the output changes almost immediately (there is a small delay as signals propagate through the circuit).
Sequential circuits use a clock and require storage elements such as flip flops . As a result, changes in the output are synchronised to the circuit clock and are not immediate. We talk more specifically about modelling combinational logic in this post, whilst sequential logic is discussed in the next post.
The simplest elements to model in VHDL are the basic logic gates – AND, OR, NOR, NAND, NOT and XOR.
Each of these type of gates has a corresponding operator which implements their functionality. Collectively, these are known as logical operators in VHDL.
To demonstrate this concept, let us consider a simple two input AND gate such as that shown below.
The VHDL code shown below uses one of the logical operators to implement this basic circuit.
Although this code is simple, there are a couple of important concepts to consider. The first of these is the VHDL assignment operator (<=) which must be used for all signals. This is roughly equivalent to the = operator in most other programming languages.
In addition to signals, we can also define variables which we use inside of processes. In this case, we would have to use a different assignment operator (:=).
It is not important to understand variables in any detail to model combinational logic but we talk about them in the post on the VHDL process block .
The type of signal used is another important consideration. We talked about the most basic and common VHDL data types in a previous post.
As they represent some quantity or number, types such as real, time or integer are known as scalar types. We can't use the VHDL logical operators with these types and we most commonly use them with std_logic or std_logic_vectors.
Despite these considerations, this code example demonstrates how simple it is to model basic logic gates.
We can change the functionality of this circuit by replacing the AND operator with one of the other VHDL logical operators.
As an example, the VHDL code below models a three input XOR gate.
The NOT operator is slightly different to the other VHDL logical operators as it only has one input. The code snippet below shows the basic syntax for a NOT gate.
- Mixing VHDL Logical Operators
Combinational logic circuits almost always feature more than one type of gate. As a result of this, VHDL allows us to mix logical operators in order to create models of more complex circuits.
To demonstrate this concept, let’s consider a circuit featuring an AND gate and an OR gate. The circuit diagram below shows this circuit.
The code below shows the implementation of this circuit using VHDL.
This code should be easy to understand as it makes use of the logical operators we have already talked about. However, it is important to use brackets when modelling circuits with multiple logic gates, as shown in the above example. Not only does this ensure that the design works as intended, it also makes the intention of the code easier to understand.
- Reduction Functions
We can also use the logical operators on vector types in order to reduce them to a single bit. This is a useful feature as we can determine when all the bits in a vector are either 1 or 0.
We commonly do this for counters where we may want to know when the count reaches its maximum or minimum value.
The logical reduction functions were only introduced in VHDL-2008. Therefore, we can not use the logical operators to reduce vector types to a single bit when working with earlier standards.
The code snippet below shows the most common use cases for the VHDL reduction functions.
Mulitplexors in VHDL
In addition to logic gates, we often use multiplexors (mux for short) in combinational digital circuits. In VHDL, there are two different concurrent statements which we can use to model a mux.
The VHDL with select statement, also commonly referred to as selected signal assignment, is one of these constructs.
The other method we can use to concurrently model a mux is the VHDL when else statement.
In addition to this, we can also use a case statement to model a mux in VHDL . However, we talk about this in more detail in a later post as this method also requires us to have an understanding of the VHDL process block .
Let's look at the VHDL concurrent statements we can use to model a mux in more detail.
VHDL With Select Statement
When we use the with select statement in a VHDL design, we can assign different values to a signal based on the value of some other signal in our design.
The with select statement is probably the most intuitive way of modelling a mux in VHDL.
The code snippet below shows the basic syntax for the with select statement in VHDL.
When we use the VHDL with select statement, the <mux_out> field is assigned data based on the value of the <address> field.
When the <address> field is equal to <address1> then the <mux_out> signal is assigned to <a>, for example.
We use the the others clause at the end of the statement to capture instance when the address is a value other than those explicitly listed.
We can exclude the others clause if we explicitly list all of the possible input combinations.
- With Select Mux Example
Let’s consider a simple four to one multiplexer to give a practical example of the with select statement. The output Q is set to one of the four inputs (A,B, C or D) depending on the value of the addr input signal.
The circuit diagram below shows this circuit.
This circuit is simple to implement using the VHDL with select statement, as shown in the code snippet below.
VHDL When Else Statements
We use the when statement in VHDL to assign different values to a signal based on boolean expressions .
In this case, we actually write a different expression for each of the values which could be assigned to a signal. When one of these conditions evaluates as true, the signal is assigned the value associated with this condition.
The code snippet below shows the basic syntax for the VHDL when else statement.
When we use the when else statement in VHDL, the boolean expression is written after the when keyword. If this condition evaluates as true, then the <mux_out> field is assigned to the value stated before the relevant when keyword.
For example, if the <address> field in the above example is equal to <address1> then the value of <a> is assigned to <mux_out>.
When this condition evaluates as false, the next condition in the sequence is evaluated.
We use the else keyword to separate the different conditions and assignments in our code.
The final else statement captures the instances when the address is a value other than those explicitly listed. We only use this if we haven't explicitly listed all possible combinations of the <address> field.
- When Else Mux Example
Let’s consider the simple four to one multiplexer again in order to give a practical example of the when else statement in VHDL. The output Q is set to one of the four inputs (A,B, C or D) based on the value of the addr signal. This is exactly the same as the previous example we used for the with select statement.
The VHDL code shown below implements this circuit using the when else statement.
- Comparison of Mux Modelling Techniques in VHDL
When we write VHDL code, the with select and when else statements perform the same function. In addition, we will get the same synthesis results from both statements in almost all cases.
In a purely technical sense, there is no major advantage to using one over the other. The choice of which one to use is often a purely stylistic choice.
When we use the with select statement, we can only use a single signal to determine which data will get assigned.
This is in contrast to the when else statements which can also include logical descriptors.
This means we can often write more succinct VHDL code by using the when else statement. This is especially true when we need to use a logic circuit to drive the address bits.
Let's consider the circuit shown below as an example.
To model this using a using a with select statement in VHDL, we would need to write code which specifically models the AND gate.
We must then include the output of this code in the with select statement which models the multiplexer.
The code snippet below shows this implementation.
Although this code would function as needed, using a when else statement would give us more succinct code. Whilst this will have no impact on the way the device works, it is good practice to write clear code. This help to make the design more maintainable for anyone who has to modify it in the future.
The VHDL code snippet below shows the same circuit implemented with a when else statement.
Instantiating Components in VHDL
Up until this point, we have shown how we can use the VHDL language to describe the behavior of circuits.
However, we can also connect a number of previously defined VHDL entity architecture pairs in order to build a more complex circuit.
This is similar to connecting electronic components in a physical circuit.
There are two methods we can use for this in VHDL – component instantiation and direct entity instantiation .
- VHDL Component Instantiation
When using component instantiation in VHDL, we must define a component before it is used.
We can either do this before the main code, in the same way we would declare a signal, or in a separate package.
VHDL packages are similar to headers or libraries in other programming languages and we discuss these in a later post.
When writing VHDL, we declare a component using the syntax shown below. The component name and the ports must match the names in the original entity.
After declaring our component, we can instantiate it within an architecture using the syntax shown below. The <instance_name> must be unique for every instantiation within an architecture.
In VHDL, we use a port map to connect the ports of our component to signals in our architecture.
The signals which we use in our VHDL port map, such as <signal_name1> in the example above, must be declared before they can be used.
As VHDL is a strongly typed language, the signals we use in the port map must also match the type of the port they connect to.
When we write VHDL code, we may also wish to leave some ports unconnected.
For example, we may have a component which models the behaviour of a JK flip flop . However, we only need to use the inverted output in our design meaning. Therefore, we do not want to connect the non-inverted output to a signal in our architecture.
We can use the open keyword to indicate that we don't make a connection to one of the ports.
However, we can only use the open VHDL keyword for outputs.
If we attempt to leave inputs to our components open, our VHDL compiler will raise an error.
- VHDL Direct Entity Instantiation
The second instantiation technique is known as direct entity instantiation.
Using this method we can directly connect the entity in a new design without declaring a component first.
The code snippet below shows how we use direct entity instantiation in VHDL.
As with the component instantiation technique, <instance_name> must be unique for each instantiation in an architecture.
There are two extra requirements for this type of instantiation. We must explicitly state the name of both the library and the architecture which we want to use. This is shown in the example above by the <library_name> and <architecture_name> labels.
Once the component is instantiated within a VHDL architecture, we use a port map to connect signals to the ports. We use the VHDL port map in the same way for both direct entity and component instantiation.
Which types can not be used with the VHDL logical operators?
Scalar types such as integer and real.
Write the code for a 4 input NAND gate
We can use two different types of statement to model multiplexors in VHDL, what are they?
The with select statement and the when else statement
Write the code for an 8 input multiplexor using both types of statement
Write the code to instantiate a two input AND component using both direct entity and component instantiation. Assume that the AND gate is compiled in the work library and the architecture is named rtl.
Leave a Reply Cancel reply
Your email address will not be published. Required fields are marked *
Save my name, email, and website in this browser for the next time I comment.
Signal Assignments in VHDL: with/select, when/else and case
Sometimes, there is more than one way to do something in VHDL. OK, most of the time , you can do things in many ways in VHDL. Let’s look at the situation where you want to assign different values to a signal, based on the value of another signal.
With / Select
The most specific way to do this is with as selected signal assignment. Based on several possible values of a , you assign a value to b . No redundancy in the code here. The official name for this VHDL with/select assignment is the selected signal assignment .
When / Else Assignment
The construct of a conditional signal assignment is a little more general. For each option, you have to give a condition. This means that you could write any boolean expression as a condition, which give you more freedom than equality checking. While this construct would give you more freedom, there is a bit more redundancy too. We had to write the equality check ( a = ) on every line. If you use a signal with a long name, this will make your code bulkier. Also, the separator that’s used in the selected signal assignment was a comma. In the conditional signal assignment, you need the else keyword. More code for the same functionality. Official name for this VHDL when/else assignment is the conditional signal assignment
Combinational Process with Case Statement
The most generally usable construct is a process. Inside this process, you can write a case statement, or a cascade of if statements. There is even more redundancy here. You the skeleton code for a process (begin, end) and the sensitivity list. That’s not a big effort, but while I was drafting this, I had put b in the sensitivity list instead of a . Easy to make a small misstake. You also need to specify what happens in the other cases. Of course, you could do the same thing with a bunch of IF-statements, either consecutive or nested, but a case statement looks so much nicer.
While this last code snippet is the largest and perhaps most error-prone, it is probably also the most common. It uses two familiar and often-used constructs: the process and the case statements.
Hard to remember
The problem with the selected and conditional signal assignments is that there is no logic in their syntax. The meaning is almost identical, but the syntax is just different enough to throw you off. I know many engineers who permanenty have a copy of the Doulos Golden Reference Guide to VHDL lying on their desks. Which is good for Doulos, because their name gets mentioned all the time. But most people just memorize one way of getting the job done and stick with it.
- VHDL Pragmas (blog post)
- Records in VHDL: Initialization and Constraining unconstrained fields (blog post)
- Finite State Machine (FSM) encoding in VHDL: binary, one-hot, and others (blog post)
- "Use" and "Library" in VHDL (blog post)
- The scope of VHDL use clauses and VHDL library clauses (blog post)
Tutorial – Introduction to VHDL
VHDL is a horrible acronym. It stands for V HSIC H ardware D escription L anguage. An acronym inside an acronym, awesome! VHSIC stands for V ery H igh S peed I ntegrated C ircuit. Therefore, VHDL expanded is V ery High Speed Integrated Circuit H ardware D escription L anguage. PHEW that’s a mouthful. VHDL is one of the two languages used by education and business to design FPGAs and ASICs. You might first benefit from an introduction to FPGAs and ASICs if you are unfamiliar with these fascinating pieces of circuitry. VHDL and Verilog are the two languages digital designers use to describe their circuits, and they are different by design than your traditional software languages such as C and Java.
For the example below, we will be creating a VHDL file that describes an And Gate. As a refresher, a simple And Gate has two inputs and one output. The output is equal to 1 only when both of the inputs are equal to 1. Below is a picture of the And Gate that we will be describing with VHDL.
Let’s get to it! The fundamental unit of VHDL is called a signal . For now let’s assume that a signal can be either a 0 or a 1 (there are actually other possibilities, but we will get to that). Here is some basic VHDL logic:
The first line of code defines a signal of type std_logic and it is called and_gate. Std_logic is the type that is most commonly used to define signals, but there are others that you will learn about. This code will generate an AND gate with a single output (and_gate) and 2 inputs (input_1 and input_2). The keyword “and” is reserved in VHDL. The <= operator is known as the assignment operator. When you verbally parse the code above, you can say out loud, “The signal and_gate GETS input_1 and-ed with input_2.”
Now you may be asking yourself where input_1 and input_2 come from. Well as their name implies they are inputs to this file, so you need to tell the tools about them. Inputs and outputs to a file are defined in an entity . An entity contains a port that defines all inputs and outputs to a file. Let’s create a simple entity:
This is your basic entity. It defines an entity called example_and and 3 signals, 2 inputs and 1 output, all of which are of type std_logic. One other VHDL keyword is needed to make this complete and that is architecture . An architecture is used to describe the functionality of a particular entity. Think of it a thesis paper: the entity is the table of contents and the architecture is the content. Let’s create an architecture for this entity:
The above code defines an architecture called rtl of entity example_and. All signals that are used by the architecture must be defined between the “is” and the “begin” keywords. The actual architecture logic comes between the “begin” and the “end” keywords. You’re almost done with this file. One last thing you need to tell the tools is which library to use. A library defines how certain keywords behave in your file. For now, just take it for granted that you need to have these 2 lines at the top of your file:
Congratulations! You have created your first VHDL file. You can see the completed file here:
Does it seem like you had to write a lot of code just to create a stupid and gate? First of all, and gates aren’t stupid. Secondly, you are correct; VHDL is a very verbose language. Get used to the fact that doing something that was very easy in software will take you significantly longer in an HDL such as Verilog or VHDL. But just ask some software guy to try to generate an image to a VGA monitor that displays Conway’s Game of Life and watch their head spin in amazement! By the way, that video is created with VHDL and an FPGA. You will be able to do that soon enough!
Next we will discuss another fundamental VHDL keyword: process.
Thanks. This was a very helpful example for someone in another continent trying to figure out how to get a professor’s whiteboard drawings of circuits accessible to a blind student. They asked me because of this. https://research.library.kutztown.edu/cisfaculty/5/
I’ve been trying to use your website for some weeks now, but there’s a google ad banner that covers the content. Could you please do something about this? It’s practically impossible to do anything and to be honest, I’d have used another website if I didn’t have a go board. Thank you.
I’ve turned off auto-ads on the site. Please let me know if this problem still exists!
Leave A Comment Cancel reply
Save my name, email, and website in this browser for the next time I comment.
Get full access to VHDL and 60K+ other titles, with a free 10-day trial of O'Reilly.
There are also live events, courses curated by job role, and more.
- Introduction to dataflow modelling
- Understand the differences between concurrent and sequential signal assignment statements
- Explore the concurrency of VHDL
- Learn about conditional assignment statements
- Use of blocks in VHDL
- Use of generate statements to allow iterations and looping in concurrent modelling
- Concurrent assertion statements
Dataflow modelling describes the architecture of the entity under design without describing its components in terms of flow of data from input towards output. This style is nearest to RTL description of the circuit. Dataflow modelling is concurrent style of modelling in VHDL, that is, unlike behavioural modelling the order of statements is not important ...
Get VHDL now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.
Don’t leave empty-handed
Get Mark Richards’s Software Architecture Patterns ebook to better understand how to design components—and how they should interact.
It’s yours, free.
Check it out now on O’Reilly
Dive in for free with a 10-day trial of the O’Reilly learning platform—then explore all the other resources our members count on to build skills and solve problems every day.