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.

Combinational Logic

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.

Table of Contents

Sign up free for exclusive content.

Don't Miss Out

We are about to launch exclusive video content. Sign up to hear about it first.

Data Types in VHDL

In this article, we shall discuss data types in VHDL. After reading this article, you’ll be able to answer the following questions.

What are data types?

  • Why are they important?
  • What are the different types of data types, and what are their subtypes?

Data types are just attributes attached to the data that helps the VHDL compiler in understanding how to treat that particular data. In simpler words, these are special commands that tell the VHDL compiler what something is and what it is supposed to do next.

In VHDL, we define datatypes while initializing signals, variables, constants, and generics.

Also, VHDL allows users to define their own data types according to their needs, and those are called user-defined data types.

User-defined data types can be defined in a separate file and shared as a library. You can define a bunch of custom data types and put them in a library and use that whenever you want. Sort of like your personal toolkit!

One of the popular standard libraries is from IEEE, which contains many useful and extensive data types, functions, and components declaration.

Due to its usefulness, it is the most popular and widely used library in VHDL. It has useful datatypes like std_logic and std_ulogic which helps us to make simulation much more practical. And to make our VHDL programming easy, we use IEEE’s library and its functions quite often.

Significance of datatypes

Let’s understand this with an analogy. Just imagine you want to store apples & oranges on a shelf. For which you decided to use cardboard boxes having a label of the fruit it consists.

Now, what if you have to store apple juice and orange juice? Now you can’t use cardboard boxes anymore, and you’ll need plastic or metallic watertight containers. So, the type of container depends on what we want to store in it.

Similarly, we store data values in variables of a suitable type. And the same analogy continues for other data objects like signals, constants, etc.

In VHDL, we have a variety of data types that were necessary to make simulations as practical as possible. All data types and their properties like the range of values it can accept are somewhere defined in a library.

When we talk about predefined datatypes in VHDL, we mean by the data types described in the standard library only. Let’s now look at all those datatypes.

A more technical example :

Consider a ‘signal Q’ whose datatype we don’t know yet. It is initialized with a value ‘0’. If we wish to change its value to ‘1’ later on. How we’ll do it?

You may say the below statement will do the job easily.

But wait and think, you don’t know yet if it is of type bit , integer , character or any other.

As a programmer, you have the freedom to use a data type, but you should also utilize your wisdom to choose a suitable one.

Data types in the standard library

There are many data types defined in the standard library of VHDL. To make them easy to understand, we categorize them into the following four types:

Enumerated type

Numeric type, miscellaneous.

Now let’s understand them all one by one.

These datatypes can take several values listed/ enumerated in the standard library. Enumerated data types consist of the following types:

  • Severity level

Boolean data type

A Boolean type data object can have a single value. Either ‘FALSE’ or ‘TRUE.’ That’s it. The logical operations that can be performed on Boolean variables are “and, or, not, nand, nor, xor.”

Initializing a Boolean variable and a signal without an initial value:

Initializing a Boolean variable and a signal with an initial value:

Bit data type

A Bit type of data object can either have ‘0’ or ‘1’. The logical operations that can be performed on Bit variables are the same as of Boolean, i.e. “and, or, not, nand, nor, xor.”

Initializing a Bit type variable and a signal without an initial value:

Initializing a Bit type variable and a signal with an initial value:

Character data type

A character type data object can hold any one character or special character at a time or can hold sum defined literal like NUL, SOX, STX, etc.

Initializing a character variable without an initial value:

Initializing a character variable with an initial character:

All possible enumeration for a character data type

Severity levels.

The severity level data type can have the values ‘NOTE’, ‘WARNING,’ ‘ERROR,’ ‘FAILURE.’ Severity levels are used in assertion statements, which will be discussed in detail in an upcoming article, but, in short, they behave as logs (think of them like personal paper flags) while simulation to indicate if any error occurs and what is its severity.

When we initialize a data object without value, its default value is set to the leftmost listed value from the library. For example, in library enumeration for ‘BIT’ is

So default value for data objects of datatype bit is ‘0’. And the same goes for all data types as mentioned in the table below

As the name suggests, these data types can hold numeric values only. Numeric data type consists of the following types:

Integer data type

It can hold an integer number ranging from -(2 31 – 1) to +(2 31 – 1). Interestingly two subtypes of integers are also defined in the standard library of VHDL.

Now, what are subtypes you ask, in short, a subtype is a datatype which has constrained values of its base type. Sound confusing?

Here’s an example, consider the statement below

This creates a subtype named ‘MY_INTEGER’ of base type ‘INTEGER’ with values ranging from 50 to 150.

Two subtypes that are defined in the standard library are

  • ‘NATURAL’ having a range from 0 to +(2 31 – 1)
  • ‘POSITIVE’ having a range of 1 to +(2 31 – 1).

Initialising a natural variable

Initialising a positive variable

You can also create your own subtype of any datatype using type declaration, we will look into that in a future article.

Real data type

It can hold floating-point numbers ranging from -1.0E38 to +1.0E38. These are very helpful for precise calculation. For example, if we need to use the value of pi (π) for some calculations, then we can’t use an integer to store its value (3.14159). An integer can only store 3, which decreases preciseness of calculations. But a real can store floating digits of up to 6 decimal places.

Array data types

An array is a collection of objects of the same type. There are two arrays predefined in the standard library

String – A string is simply a 1-Dimensional array of characters.

Bit vector -A bit_vector is simply an array of grouped bits, they are useful while defining multiple pin inputs. Consider an example. You are creating a 4-bit adder so you’ll need 4-bit inputs, rather than defining them individually you can use:

The above statement defines a 4-bit input. To access them individually, we can use input(0) to access the first bit, input(1) for the second, and so on. This also helps us while writing testbenches. Assigning values to vectors is way easier. Check out this example:

The statement above assigns ‘0’ to input(0), ‘1’ to input(1), and so on.

There are two data types in the standard library, i.e., ‘TIME.’ This is used to store values that can be further utilized for timing operation, like creating specific delays. Some units of time are also defined in the standard library, as shown below:

Initializing a time variable with an initial value

Data types from non-standard libraries

These datatypes can take several values all listed/ enumerated in their respective library. Enumerated data types from popular libraries are:

Std_ulogic – We pronounce it as ‘standard u logic’ or ‘standard unresolved logic.’

We use it to represent much more practical details of digital signals in circuits and wires.

All enumeration for a Std_ulogic data type is listed below

'U' : Uninitialized.

'X' : Unknown. Impossible to determine this value/result.

'0' : logic 0

'1' : logic 1

'Z' : High Impedance

'W' : Weak signal, can’t tell if it should be 0 or 1.

'L' : This signal is also weak that it should probably go to 0

'H' : This signal is also weak but it should probably go to 1

'-' : Don’t care.

Initializing a Std_ulogic  type variable and a signal without an initial value-

Initializing a Std_ulogic  type variable and a signal with an initial value-

std_logic – This datatype has the same enumeration as of std_ulogic . However, the difference is that std_logic is resolved and we don’t need extra resolution function.

'U' : uninitialized. Any value is not assigned to the signal yet.

'X' : unknown. Impossible to determine this value/result.

Initializing a Std_logic type variable and a signal without an initial value:

Initializing a Std_logic type variable and a signal with an initial value:

Std_ulogic_vector  – A mentioned earlier, an array is a collection of objects of the same type. So here also when we want to initialize a multi-bit input, we use vector notation to create a vector of multiple std_ulogic bits.

The above statement defines a 4-bit input. To access them individually, we can use input(0) to access the first bit, input(1) for the second, and so on. This also helps us while writing testbenches. Assigning values to vectors is way easier, see example-

Std_logic_vector

This is also similar to other vector datatypes; therefore, its initialization and assignment operators are the same.

Initializing a std_logic_vector type signal array-

Value assignment to the signal array-

Record – It is a special datatype, and we use it to club many data objects of the same or different data types. You can also understand it as a user-defined datatype. It is analogous to structure in C programming language .

In the code above, we have created a record named ‘MODULE,’ and it has 4 data objects inside it. Now MODULE is a datatype in itself.

SIZE of type INTEGER and can only accept values in the range of 50-100.

DELAY of type TIME

NO_OF_INPUTS of type BIT .

NO_OF_OUTPUTS of type BIT .

Initializing a record

Above line of code, creates a data object of type MODULE named AND_COMP

Now, assigning values to a record

The above line of code assigns “50” to SIZE, “20 ns” to DELAY, “3” to NO_OF_INPUTS, and “2” to NO_OF_OUTPUTS.

You may assign value to each element separately.

Let’s see some examples of VHDL, and we will focus on the datatypes that we are using.

Bit and bit_vector

We will be talking only about the program of 2×1 multiplexer , so if you are interested in working on it, then we have a separate article here .

In the above code, three ports are initialized, two inputs, and one output. For data input in 2×1 mux, we need 2-bit input we may use two different bits as

To assign values to both will take two lines of code as

But this is not efficient, so we used bit_vector notation and used the following code

This creates 2-bit input as input(0) and input(1) and assigning values to them is way more comfortable as

One may argue that it is just a matter of one line, so you should also think that it is also just a 2×1 mux. For instance, if we are programming a 32×1 mux, then, just for providing input, we would have needed 32 lines of code. But using bit_vector that can also be summed up in one line.

To summarize, we have studied all the standard predefined data types in the VHDL language. After that, we have discussed all the popular non-standard data types. For all data types, we have discussed their initialization and assignments syntaxes and their use cases.

As always, if you have any queries, we would love to address them. Just drop in a comment in the comments section below.

About the author

Related courses to Data Types in VHDL

Verilog course

A free and complete Verilog course for students. Learn everything from scratch including syntax, different modeling styles and testbenches.

CMOS - IC Design Course

A free course as part of our VLSI track that teaches everything CMOS. Right from the physics of CMOS to designing of logic circuits using the CMOS inverter.

Fundamentals

  • Every signal has a type
  • Type specifies possible values
  • Types has to be defined at signal declaration …
  • entity: port declaration, or in
  • architecture: signal declaration
  • Types have to match

In VHDL, signals must have a data type associated with them that limits the number of possible values. This type has to be fixed when the signal is declared, either as entity port or an internal architecture signal, and can not be changed during runtime. Whenever signal values are updated, the data types on both sides of the assignment operator ’⇐’ have to match.

Standard Data Types

  • Every type has a number of possible values
  • Standard types are defined by the language
  • User can define his own types

A number of data types are already defined in the standard package which is always implicitly referenced.

’ boolean ’ is usually used to control the flow of the VHDL execution while ‘ bit ’ uses level values (’ 0 ’, ’ 1 ’) instead of truth values (’ false ’, ’ true ’) and is therefore better suited to model wires. Number values can be communicated via signals of type ’ integer ’ or ’ real ’.

The actual range and accuracy depends on the platform implementation and only lower bounds are defined, e.g. integers are guaranteed to be at least 32 bits wide. Floating point operations can not be synthesized automatically, yet, i.e. the use of ’ real ’ data types is restricted to testbench applications.

The same applies to ’ character ’ and ’ time ’.

Real types are not synthesizeable:

  • You have to decide how many bits will be used for the digits pre and after the decimal point!
  • you have to use synthesizeable division algorithms to calculate them

Data type ‘time’

  • Testbenches
  • Gate delays
  • Multiplied/divided by integer/real
  • Returns TIME type
  • Internally in smallest unit (fs)
  • Available time units 
fs, ps, ns, us, ms, sec, min, hr

’ time ’ is a special data type as it consists out of a numerical value and a physical unit.

It is used to delay the execution of statements for a certain amount of time, e.g. in testbenches or to model gate and propagation delays. Signals of data type ’ time ’ can be multiplied or divided by ’ integer ’ and ’ real ’ values. The result of these operations remains of data type ’ time ’.

The internal resolution of VHDL simulators is set to femto-seconds (fs).

Definition of Arrays

  • Collection of signals of the same type
  • bit_vector (array of bit)
  • string (array of character)
  • Unconstrained arrays: definition of actual size during signal/port declaration

Arrays are useful to group signals of the same type and meaning.

Two unconstrained array data types, i.e. whose range is not limited, are predefined in VHDL:

  • ’ bit_vector ’ and ’ string ’ are arrays of ’ bit ’ and ’ character ’ values, respectively.

Please note that the array boundaries have to be fixed during signal declarations, e.g. ’bit_vector(3 downto 0)’.

Only constrained arrays may be used as entity ports or architecture signals.

‘integer’ and ‘bit’ Types

  • Example for using ‘bit’ and ‘integer’

Integer signals will be mapped to a number of wires during synthesis.

These wires could be modelled via bit vectors as well, yet ’ bit_vector ’ signals do not have a numerical interpretation associated with them.

Therefore the synthesis result for the two example architectures would be the same. The process models a simple multiplexer which selects the input A as source for its output Z when the select signal SEL is ’1’ and the input B otherwise.

Please note that the multiplexer process is exactly the same for both data types!

Assignments with Array Types

  • Z_BUS(3) ⇐ C_BUS(0)
  • Z_BUS(2) ⇐ C_BUS(1)
  • Z_BUS(1) ⇐ C_BUS(2)
  • Z_BUS(0) ⇐ C_BUS(3)

Special care is necessary when signal assignments with arrays are carried out.

Although the data type and the width of the signals have to match, this is not true for the order of the array elements.

The values are assigned according to their position within the array, not according to their index.

Therefore it is highly recommended to use only one direction (usually ’ downto ’ in hardware applications) throughout your designs.

Bit String Literals

  • Single bit values are enclosed in '.'
  • optional base specification (default: binary)
  • Values may be separated by underscores to improve readability

The specification of signal values is different for the base types ’character’ and ’bit’ and their corresponding array types ’string’ and ’bit_vector’. Single values are always enclosed in single quotation marks (’), while double quotation marks (“) are used to specify array values.

As bit vectors are often used to represent numerical values, VHDL offers several possibilities to increase the readability of bit vector assignments.

First, a base for the following number may be specified. Per default binary data consisting of ’0’s and ’1’s is assumed. Please note that the values have to enclosed in double quotation marks even though only a single symbol might be necessary when another base is used! Additionally, underscores (_) may be inserted at will to split long chains of numbers into smaller groups in order to improve readability.

Since VHDL’93, the same rules apply to the enhanced bit vector types ’ std_(u)logic_vector ’, which will be discussed later on, as well.

Concatenation

Concatenation operator: &

Resulting signal assignment:

  • BYTE(7) ⇐ A_BUS(3)
  • BYTE(6) ⇐ A_BUS(2)
  • BYTE(5) ⇐ A_BUS(1)
  • BYTE(4) ⇐ A_BUS(0)
  • BYTE(3) ⇐ B_BUS(3)
  • BYTE(2) ⇐ B_BUS(2)
  • BYTE(1) ⇐ B_BUS(1)
  • BYTE(0) ⇐ B_BUS(0)
  • Z_BUS(3) ⇐ A_BIT
  • Z_BUS(2) ⇐ B_BIT
  • Z_BUS(1) ⇐ C_BIT
  • Z_BUS(0) ⇐ D_BIT

As signal assignments require matching data types on both sides of the operator it is sometimes necessary to assemble an array in the VHDL code.

The concatenation operator ’ & ’ groups together the elements on its sides which have to be of the same data type, only.

Again, the array indices are ignored and only the position of the elements within the arrays is used. The concatenation operator may be used on the right side of signal assignments, only!

  • Aggregates bundle signals together
  • May be used on both sides of an assignment
  • Keyword ‘other’ selects all remaining elements

Another way of assigning signals which does not suffer from this limitation is via the aggregate construct.

Here, the signals that are to build the final array are enclosed in a ’(’ ’)’ pair and separated by ’,’.

Instead of a simple concatenation, it is also possible to address the array elements explicitly by their corresponding index, as shown in the last signal assignment statement of the aggregate example.

The keyword ’ others ’ may be used to select those indices that have not been addressed, yet.

Slices of Array

  • Slices select elements of arrays

The inverse operation of concatenation and aggregation is the selection of slices of arrays, i.e. only a part of an array is to be used.

The range of the desired array slice is specified in brackets and must match the range declaration of the signal!

Of course, it is possible to select only single array elements.

Chapters of System Design > VHDL Language and Syntax

  • General Issues
  • VHDL Structural Elements
  • Process Execution
  • Extended Data Types
  • Sequential Statements
  • Subprograms
  • Subprogram Declaration and Overloading
  • Concurrent Statements

assignment types vhdl

GitHub

Variables vs. Signals in VHDL

Variables and Signals in VHDL appears to be very similar. They can both be used to hold any type of data assigned to them. The most obvious difference is that variables use the := assignment symbol whereas signals use the <= assignment symbol. However the differences are more significant than this and must be clearly understood to know when to use which one. If you need a refresher, try this page about VHDL variables .

Signals vs. Variables:

  • Variables can only be used inside processes, signals can be used inside or outside processes.
  • Any variable that is created in one process cannot be used in another process, signals can be used in multiple processes though they can only be assigned in a single process .
  • Variables need to be defined after the keyword process but before the keyword begin . Signals are defined in the architecture before the begin statement.
  • Variables are assigned using the := assignment symbol. Signals are assigned using the <= assignment symbol.
  • Variables that are assigned immediately take the value of the assignment. Signals depend on if it’s combinational or sequential code to know when the signal takes the value of the assignment.

The most important thing to understand (and the largest source of confusion) is that variables immediately take the value of their assignment, whereas signals depend on if the signal is used in combinational or sequential code . In combinational code, signals immediately take the value of their assignment. In sequential code, signals are used to create flip-flops, which inherently do not immediately take the value of their assignment. They take one clock cycle. In general, I would recommend that beginners avoid using variables. They can cause a lot of confusion and often are hard to synthesize by the tools.

The example below demonstrates how signals behave differently than variables. Notice that r_Count and v_Count appear to be the same, but they actually behave very differently.

Variables can be a bit tricky to display in simulation. If you are using Modelsim, read more about how to see your variables in Modelsim’s waveform window . Look carefully at the waveform above. Do you see how o_var_done pulses every 5th clock cycle, but o_sig_done pulses every 6th clock cycle? Using signals and variables to store data generates very different behavior . Make sure you clearly understand what you code will be generating and make sure that you simulate your code to check that behaves like you want!

Learn Verilog

Leave A Comment Cancel reply

Save my name, email, and website in this browser for the next time I comment.

In VHDL -93, a variable assignment may have a label:

assignment types vhdl

  • Product Manual
  • Release Notes
  • Screencasts
  • Tech Articles

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)

VIDEO

  1. vhdl part 1

  2. 7 segment display using VHDL programming

  3. VHDL modellingstyles

  4. DICA:L2.2 || PROGRAMMING STRUCTURE OF VHDL || BY:G.SANDHYA RANI

  5. VhDL VGA assignment(2)

  6. VhDL VGA assignment(1)

COMMENTS

  1. An Introduction to VHDL Data Types

    bit Type in VHDL. The bit type is the simplest of all types in VHDL. We use this type to model a single logical value within our FPGA. The bit type can only ever have a value or either 1b or 0b. The code snippet below shows the method we use to declare a bit type signal in VHDL. signal <signal_name> : bit;

  2. VHDL Logical Operators and Signal Assignments for Combinational Logic

    The VHDL code shown below uses one of the logical operators to implement this basic circuit. and_out <= a and b; 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.

  3. PDF VHDL Syntax Reference

    1 1. Bits, Vectors, Signals, Operators, Types 1.1 Bits and Vectors in Port Bits and vectors declared in port with direction. Example: port ( a : in std_logic; -- signal comes in to port a from outside b : out std_logic; -- signal is sent out to the port b c : inout std_logic; -- bidirectional port x : in std_logic_vector(7 downto 0); -- 8-bit input vector

  4. Assignment Symbol

    In VHDL there are two assignment symbols: <= Assignment of Signals. := Assignment of Variables and Signal Initialization. Either of these assignment statements can be said out loud as the word "gets". So for example in the assignment: test <= input_1; You could say out loud, "The signal test gets (assigned the value from) input_1.".

  5. vhdl

    1. Assignments in VHDL are neighter specified as registered or combinatorial. In VHDL the actual assignment type (the type of RTL logic generated) is just inferred. Registers in VHDL are created explicitly by assigning a signal on a clock edge, though just because a process has a clock it does not mean all signals in that block will be assigned ...

  6. Data Types in VHDL

    Integer data type. It can hold an integer number ranging from - (2 31 - 1) to + (2 31 - 1). Interestingly two subtypes of integers are also defined in the standard library of VHDL. Now, what are subtypes you ask, in short, a subtype is a datatype which has constrained values of its base type.

  7. VHDL Syntax Reference

    The most basic of complete VHDL statements, a signal assignment is likely also one of the most common. Syntax: < signal_name > <= < expression >; -- the expression must be of a form whose result matches. the type of the assigned signal. Examples: std_logic_signal_1 <= not std_logic_signal_2; std_logic_signal <= signal_a and signal_b;

  8. VHDL Basics

    The standard package defines built-in VHDL data types that can be used for designing and associated operations that go along with them. The textio package provides support for file operations, for example reading and writing to external data files. ... The final type of assignment is known as a selected signal assignment. A selected assignment ...

  9. courses:system_design:vhdl_language_and_syntax:data_types ...

    In VHDL, signals must have a data type associated with them that limits the number of possible values. This type has to be fixed when the signal is declared, either as entity port or an internal architecture signal, and can not be changed during runtime. Whenever signal values are updated, the data types on both sides of the assignment operator ...

  10. PDF Concurrent Statements

    Signal Assignment with Busses A bus is a collection of wires related in some way by function or clock domain. Examples would be an address bus or data bus. In VHDL we refer to busses as a vector. For example:--8-bit bus consisting of 8 wires carrying signals of-- type std_logic--all these wires may be referred to by the name big_bus

  11. Variables vs. Signals in VHDL

    Variables and Signals in VHDL appears to be very similar. They can both be used to hold any type of data assigned to them. The most obvious difference is that variables use the := assignment symbol whereas signals use the <= assignment symbol. However the differences are more significant than this and must be clearly understood to know when to ...

  12. VHDL Reference Guide

    Variable assignments are generally synthesisable, providing they use types and operators acceptable to the synthesis tool. In a "clocked process", each variable which has its value read before it has had an assignment to it will be synthesised as the output of a register. ... In VHDL-93, a variable assignment may have a label: label: variable ...

  13. Concurrent Conditional and Selected Signal Assignment in VHDL

    Conditional Signal Assignment or the "When/Else" Statement. The "when/else" statement is another way to describe the concurrent signal assignments similar to those in Examples 1 and 2. Since the syntax of this type of signal assignment is quite descriptive, let's first see the VHDL code of a one-bit 4-to-1 multiplexer using the ...

  14. Signal Assignments in VHDL: with/select, when/else and case

    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. with a select b <= "1000" when "00", "0100" when "01", "0010" when "10 ...

  15. Review of VHDL Signed/Unsigned Data Types

    In recent articles we've looked at some important VHDL data types: std_logic, std_logic_vector, bit, boolean, ... For these assignments, we have to first perform type casting and then the assignment operation. Type casting is a way to convert an object from one data type to another data type. Type casting and type conversion will be discussed ...

  16. PDF Essential VHDL 7

    VHDL defines data representation types, and the scalar and array types include objects such as integer, real, and bit. For various reasons none of these are quite right for describing digital circuit values. Most synthesis tools, and simulation models, use the type std_logic from the IEEE library. The type std_logic is a

  17. syntax

    Contrary to the book Digital Mclogic Design by Bryan Mealy VHDL has no assignment operators. Assignment is a basic operation found in assignment statements and object and interface declarations. ... <= as an assignment for signal as target (for variable it is :=). ... type array_type is array(0 to 1) of std_logic_vector(7 downto 0); constant my ...

  18. VHDL Reference Guide

    Assignment to a whole record must be done using an aggregate. Positional or named association may be used type T_PACKET is record BYTE_ID : std_ulogic; PARITY : std_ulogic; ADDRESS : integer range 0 to 3; DATA : std_ulogic_vector (3 downto 0); end record signal TX_DATA : T_PACKET; ...

  19. PDF Concurrent Statements

    Delay Types. VHDL signal assignment statements prescribe an amount of time that must transpire before a signal assumes its new value. This prescribed delay can be in one of three forms: Transport: propagation delay only. Inertial: minimum input pulse width and propagation delay. Delta:

  20. concurrent and conditional signal assignment (VHDL)

    5. Where you are hinting at in your problem has nothing to do with concurrent assignments or sequential statements. It has more to do with the difference between if and case. Before we get to that first lets understand a few equivalents. The concurrent conditional assignment: Y <= A when ASel = '1' else B when BSel = '1' else C ;

  21. VHDL assignment to an array type

    type foo is array (0 downto 0) of std_logic_vector(7 downto 0); with an example assignment to a constant of: constant cFoo : foo := ( x"00", x"11" ); Moreover consider that I try to assign index 0 with another constant. For example. type foo is array (0 downto 0) of std_logic_vector(7 downto 0); constant cBar : std_logic_vector(7 downto 0);

  22. Assign values to an array partially in VHDL?

    1. I have an array in VHDL of the form, type CacheArray is array(0 to 15) of std_logic_vector(33 downto 0); signal cache_array: CacheArray := (others => (others => '0')); I wish to assign values to this array such that only one bit of each index is initialized. I suspected something like this will work,