Why do we need VHDL

Simplify VHDL code: the Std_Logic_Vector data type

Why do we need vector data types? // www.allaboutcircuits.com/technical-articles/hardware-description-langauge-getting-started-vhdl-digital-circuit-design/ "target =" _ blank "> article.
Illustration 1. A simple digital circuit.

Here is the VHDL code for this circuit:

Suppose we need to write the VHDL code for the circuit in Figure 2.

Figure 2.

We can extend the previous code to get the VHDL description of 2 as

The above code is correct; however, we shall see that it is possible to have a more compact and readable VHDL description for this circuit. The disadvantage of the above code is that it presents each of the input / output ports as individual signals and does not establish a relationship between them.

Let's consider an alternative way to represent the circuit in Figure 2.

Figure 3.

Figure 3 suggests that we can think of a0, a1, and a2 as a three-bit input port called, for example, a_vec. Similarly, input ports b0, b1 and b2 can be grouped as another three-bit input port called b_vec. What the circuit does is AND an element of a_vec with a corresponding element of b_vec. This may seem like a simple idea, but we'll see in a minute how this way of thinking makes the code more readable.

The data type "Std_Logic_Vector"

To represent a group of signals, VHDL uses vector data types. To access an element of a vector, we need to define an index. For example, let's say, as shown in Figure 4, we use a vector of length three, a_vec, to represent three values: val_0, val_1, and val_2. To access the value of an element from this vector we can use the index numbers. For example, a_vec (2) gives the value of the rightmost element of the vector in FIG. 4, which is val_2.

Figure 4. The three-element vector a_vec.

The VHDL keyword "std_logic_vector" defines a vector of elements of the type std_logic. For example, std_logic_vector (0 to 2) represents a three-element vector of the data type std_logic, with an index range from 0 to 2.

Let's use the std_logic_vector data type to describe the circuit in Figure 3. We'll use three vectors a_vec, b_vec, and out_vec to represent the blue, red, and black ports of Figure 3. With the new naming for the ports we get the following figure.

Figure 5.

The VHDL code for 5 is given below.

In lines 4 to 6 of this code, the data type "std_logic_vector" is used for the input / output ports of the circuit. Note that the AND operation on line 10 is applied to the corresponding elements of the two vectors a_vec and b_vec, i.e. a_vec (0) is ANDed with b_vec (0) and the result is assigned to out_vec (0), and so on further . Comparing this to the previous code, we observe that using the std_logic_vector data type allows for a much more compact and readable code. This advantage is particularly evident with large circuits; Imagine how unwieldy the code would be if we used individual signal assignment statements to AND the elements of two 32-bit vectors.

An ISE simulation of the above code is shown in FIG.

Figure 6. ISE simulation of the circuit shown in Figure 5.

Interpret Std_Logic_Vector data

There is one important point that must be further observed: As shown in the example above, the data type "std_logic_vector" is a way of representing a group of signals or a data bus. It is simply a sequence of ones and zeros, and there is no other interpretation for this sequence of ones and zeros. In other words, if we assign a_vec "011", it does not mean that a_vec is equal to 3 (the decimal equivalent of "011").

We cannot assume any weighting for the different bit positions of a "std_logic_vector" signal. However, we can use cast functions and use casting to interpret the sequence of ones and zeros in a given "std_logic_vector" signal as a number. The cast will be discussed in a future article.

Ascending or Descending Index Range?

So far we have used the std_logic_vector data type when defining input / output ports. Similarly, we can define a signal of the type "std_logic_vector". As an example, consider the following lines of code:

Here the first line defines a signal of the type "std_logic_vector". The index ranges from 0 to 3. Then "0010" is assigned. With this assignment, as shown in Figure 7, we have a (0) = 0, a (1) = 0, a (2) = 1, and a (3) = 0.

Figure 7.

The indexing style of this vector using the keyword "to" is called ascending. We can also use the keyword "downto" (instead of "to") if we want to have a descending index range:

In this case, as shown in Fig. 8, we have a (3) = 0, a (2) = 0, a (1) = 1 and a (0) = 0.

Figure 8.

The choice between ascending or descending order is often a matter of designer's preference, although it can be addressed by coding guidelines adopted by a particular organization. The most important thing is to choose a style and then follow it consistently. Mixing the two different styles in one project can easily lead to problems.

For example, consider the truth table for a 4-to-2 priority encoder as given below. For a priority encoder, we generally consider the leftmost bit of the input vector to be the highest priority. For example, in the following truth table, if the leftmost input bit, x (3), is high, we don't care about the state of the other three input bits and we set the outputs y and v, i.e. y = "11" and v = '1 '.

We observe that this truth table assumes that the input vector x has a descending index range since the element with the highest index is placed in the leftmost position. Now suppose that despite selecting a descending index range in the truth table, we use an ascending index range when we declare the input vector x and assign "0001" to x. In other words, we have:

Since the rightmost bit of x is high, considering the general definition for a priority encoder, we expect the outputs y and v to be "00" and "1", respectively. However, with the above code, x (3) is high, and based on the truth table above, the output will be y = "11" and v = "1". To avoid such problems, we should consistently use a descending index range throughout our code.


  • The std_logic_vector data type enables us to produce code that is much more compact and readable. This data type offers us the possibility of representing a group of signals or a data bus.
  • We cannot assume any weighting for the different bit positions of a "std_logic_vector" signal. However, we can use cast functions and use casting to interpret the sequence of ones and zeros in a given "std_logic_vector" signal as a number.
  • The index range used in a "std_logic_vector" declaration can be ascending or descending. The former uses the keyword "to" and the latter uses the keyword "downto".
  • Choosing between ascending and descending order is often a matter of style, but it's important to consistently apply that choice to a particular project.

To see a full list of my items, please visit this page.

Selected image courtesy of Altera.