View Course Path

Operators in VHDL – Easy explanation

In this post, we will take a look and understand the working of operators in VHDL. Operators are great tools that offer us room to maneuver in our program. The main purpose of any code is to implement some kind of logic. Having a variety of operators helps in that endeavor. The operators in VHDL are divided into four categories:

  • Arithmetic operators
  • Shift operators
  • Relational operators
  • Logical operators

Each operator serves a well-defined purpose, and here we will learn to use these operators to our advantage in our programs. We’ll be using all of these operators extensively in our future modules in this VHDL course. Proper usage of operators can make a rather complex task shorter. Let’s first summarize all the operators in a neat little list that you can screenshot and keep handy.

Operator Name
Arithmetic
+ addition
subtraction
* multiplication
/ division
** exponentiation
abs absolute value
not complement
mod modulo
rem remainder
+ unary plus
unary minus
& concatenation
Shift
sll shift left logical
srl shift right logical
sla
shift left arithmetic
sra
shift right arithmetic
rol rotate left
ror rotate right
shift_left()
New and more
optimum. Read
more below.
shift_right()
Relational
= test for equality
/= test for inequality
< test for less than
<=
test for less than or equal
>
test for greater than
>=
test for greater than or equal
Logical
and logical and
or logical or
nand
the logical complement of and
nor
the logical complement of or
xor
logical exclusive of or
xnor
the logical complement of exclusive of or

 

Let’s dive into these operators.

Arithmetic operators

For the sake of simplicity, let’s classify the operators into three categories.

  • Basic arithmetic operators
  • Advanced arithmetic operators
  • Special arithmetic operators

Basic arithmetic operators are used in almost every program, we will constantly come across examples, and they are easy to use with very low to no syntax restrictions.

Advanced arithmetic operators are not as frequently used but are equally important and powerful if used correctly. Again it is easy to use with a few syntax restrictions.

Special arithmetic operators perform nearly identical operations to simple arithmetic operators, the only difference being they are used under special conditions, with a specific syntax.

Basic arithmetic operators

The four basic arithmetic operators include,

  • Addition +
  • Subtraction -
  • Multiplication *
  • Division /

We can use these operators to perform basic mathematics in VHDL, and the syntax is as follows.

Addition

A simple addition operator, the syntax is as follows

<numeric> + <numeric>;

A '+' sign is used to specify the addition between two numeric values. The <numeric> is any numeric value given for addition, the yield is a summation of both the numeric values.

Subtraction

A simple subtraction operator, the syntax is as follows

<numeric> - <numeric>;

A '-' sign is used to specify the subtraction between two numeric values. The <numeric> is any numeric value given for subtraction, the yield is the difference for both the numeric values.

Multiplication

A multiplicative operator, the syntax is as follows

<numeric> * <numeric>;

A '*' sign is used to specify the multiplication between two numeric values. The <numeric> is any numeric value given for subtraction, the yield is the multiplication of both the numeric values.

Division

A Division operator, the syntax is as follows

<numeric> / <numeric>;

A '/' sign is used to specify the division between two numeric values. The <numeric> is any numeric value given for subtraction, and the yield is the quotient after the division of both the numeric values.

Any kind numeric value is allowed such as an integer, float, binary etc. Unless a certain value type is specified.

Advanced arithmetic operators

Moving on to advanced mathematical operators. Here we have the following operators:

  • Exponent  **
  • Absolute value  abs
  • Modulo  mod
  • Remainder  rem
  • Component not

These operators are extremely important for advanced mathematics in VHDL. Let us have a look at the syntax for these operators.

Exponent

For the exponent operator, the syntax is as follows:

<numeric> ** <numeric>;

A '**' sign is used to specify the use of exponentiation. The <numeric> is any numeric value given for the operation, and the yield is the exponentiation of the numeric values. Let’s use an equation to understand the syntax better.

 { <numeric> }^{ <numeric> }

Absolute value

For the absolute value operator, the syntax is as follows:

abs <numeric>;

An 'abs' is used to specify the absolute value. The <numeric> is any numeric value given for the operation, and the yield is the absolute value, a.k.a. modulus for the given numeric value.

Modulo

A modulo operator, the syntax is as follows

<integer> mod <integer>;

A 'mod' is used to specify the modulo operator. <integer> values are used for the operation, and the yield is the modulo for the given integer values.

Remainder

For the remainder operator, the syntax is as follows:

<integer> rem <integer>;

An 'rem' is used to specify the remainder operator. The <integer> values are used for the operation, and the yield is the remainder for the given integer values.

Complement

For the complement operator, the syntax is as follows:

not <logic or boolean>;

A 'not' is used to specify the complement operator. Logic or boolean data type (TRUE or FALSE) is used for this operation, the result is of the same data type and is a complement of the data provided.

Special arithmetic operators

Special arithmetic operators are used when special conditions arise. These operators include,

  • Unary plus  +
  • Unary minus  -
  • Concatenation  &

Unary plus

For the unary plus operator, the syntax is as follows:

+ <numeric>;

An '+' is used before the <numeric> to specify a unary plus operator. The <numeric> value is used for the operation, and the yield is a numeric value. When this operator is used, the numeric value returns unchanged.

Unary minus

For the unary plus operator, the syntax is as follows:

- <numeric>;

An '-' is used before the <numeric> to specify a unary minus operator. The <numeric> value is used for the operation, and the yield is a numeric value. When this operator is used, the numeric value returns with the negated sign. Remember to use this operator with parenthesis in the case of any other operator preceding it. For example, 4 * -2 is invalid. It should be 4 * (-2).

Concatenation

For the concatenation operator, the syntax is as follows:

<array or element> & <array or element>;

An '&' is used before the <array or element> to specify a concatenation operator. The <array or element> value is used for the operation, and the yield is a concatenation (joining) of the arrays or elements value.

Shift operators

Shift operators are used to shift an element of an array of numbers or alphabets left or right by a desired number of steps. Further elaboration with each operator is provided below. Shift operators include:

  • Shift Left logical  sll &  Shift Right logical srl
  • Shift Left arithmetic  sla  &  Shift Right arithmetic  sra
  • Rotate Left  rol  &  Rotate Right  ror

Shift Left logical  &  Shift Right logical

<logical array> sll <integer>; --shift left logical
<logical array> srl <integer>; --shift right logical

The sll is the left logical shifter and srl is the right logical shifter. The <integer> is used as the number of times we want to shift <logical array> left or right logically. The result of these operations is also a logical array.

Shift Left arithmetic  &  Shift Right arithmetic

<logical array> sla <integer>; --shift left arithmetic
<logical array> sra <integer>; --shift right arithmetic

The slais the left arithmetic shifter and sra is the right arithmetic shifter. The <integer> is used as the number of times we want to shift <logical array> left or right arithmetically. The result of these operations is also a logical array.

Rotate Left and Rotate Right

<logical array> rol <integer>; --rotate left 
<logical array> ror <integer>; --rotate right

The rolis the left rotator and ror is the right rotator. The <integer> is used as the number of times we want to rotate<logical array> left or right. The result of these operations is also a logical array.

Shift Functions 

A more optimum method for the implementation of shifting is by using shift functions. Shift functions are found in the numeric_std package of VHDL. These instructions have a simple syntax and are easy to understand. The keywords are shift_left() and shift_right(). The functions require two inputs: the signal to shift and the number of bits to shift by. There are two types of shifting:

  • Arithmetic shift – Here, the positions left vacant after shifting are substituted with the right bits to keep the sign of the original number intact.
  • Logical shift – Here, the positions left vacant after shifting are filled with ‘0’.

We can perform shifting logically and arithmetically use keywords unsigned and signed respectively.

Let us have a look at the syntax.

--syntax for logical shift (unsigned)
<initial_string> --contains the initial string 
<shifted_string> = shift_left(unsigned(<initial_string>), <integer>);
<shifted_string> = shift_right(unsigned(<initial_string>), <integer>);

--syntax for arithmetic shift (signed)
<initial_string> --contains the initial string 
<shifted_string> = shift_left(signed(<initial_string>), <integer>);
<shifted_string> = shift_right(signed(<initial_string>), <integer>);


--example for shigting logically (unsigned) 
<initial_string>  --contains the initial string
<shifted_string>  =  shift_left(unsigned(<initial_string>), 1); --shifts the <initial_string> towards the left logically by 1
<shifted_string> = shift_right(unsigned(<initial_string>), 1); --shifts the <initial_string> towards the right logically by 1


--example for shigting arithmetically (signed) 
<initial_string> --contains the initial string
<shifted_string> = shift_left(signed(<initial_string>), 1); --shifts the <initial_string> towards the left arithmetically by 1
<shifted_string> = shift_right(signed(<initial_string>), 1); --shifts the <initial_string> towards the right arithmetically by 1

 

The <initial_string> could be any kind of string std_logic, signed, unsigned etc. The shift_left indicates a shift towards the left and shift_right indicated a shift towards the right. And the <integer> is used to indical the number of steps we want the string to be shifted.

Relational operators

As the name suggests, relational operators are used to test the quantitative relationship of two numbers or/and characters. It could also be two strings/arrays of numbers or characters.

We use these relational operators to compare these elements, and the result is a yield of boolean values: 1=true and 0=false.

The relational operators include

  • Test for equality =  and inequality  /=
  • Test for less than < and less than or equal <=
  • Test for greater than > and greater than or equal >=

Test for equality and inequality

These operators check if the given data is equal or not. In the case of the test for equality ‘=,’ if the given data is equal, the result is a boolean true, and if unequal, the result is a boolean false.

In the case of the test for inequality ‘/=,’ if data is inequal, the result is a boolean true, and if the data is equal, the result is a boolean false. Let us use an ‘if-else’ statement to better understand the concept.

<instance_A> <instance_B> --two data instances
    process (check_equality) --Equality
       begin 
          if (<instance_A> = <instance_B>) then
          <instance_C> <= '1'; 
          else 
          <instance_C> <= '0'; 
          end if; 
    end process;

<instance_A> <instance_B> --two data instances
    process (check_inequality) --inEquality
       begin
          if (<instance_A> /= <instance_B>) then
          <instance_C> <= '1';
          else
          <instance_C> <= '0';
          end if;
    end process;

The <instance_A>, <instance_B> are data instances of any data type. In the first process, the test for equality if <instance_A> is equal to <instance_B> only then the <instance_C> is given a binary 1 value. If <instance_A> and <instance_B> are not equal the <instance_C> is given a binary 0 value.

In the second process, the test for inequality if <instance_A> is not equal to <instance_B> only then the <instance_C> is given a binary 1 value. If <instance_A> and <instance_B> are equal the <instance_C> is given a binary 0 value.

Test for less than and less than or equal

These operators check the relation for the given data A and B. In the case of less than ‘<‘, if in the given data A is less than but not equal to B, the result is a boolean true. And if A is greater than or equal to B, the result is a boolean false.

In the case of test for less than or equal ‘<=’, if A is less than or equal to B, the result is a boolean true. And if A is greater than B, the result is a boolean false. Let us use an ‘if-else’ statement to better understand the concept.

<instance_A> <instance_B> --two data instances
    process (check_lessthan) --less than
       begin 
          if (<instance_A> < <instance_B>) then
          <instance_C> <= '1'; 
          else 
          <instance_C> <= '0'; 
          end if; 
    end process;

<instance_A> <instance_B> --two data instances
    process (check_lessthan_equal) --less than or equaly
       begin
          if (<instance_A> <= <instance_B>) then
          <instance_C> <= '1';
          else
          <instance_C> <= '0';
          end if;
    end process;

The <instance_A>, <instance_B> are data instances of any data type. In the first process, the test for less than if <instance_A> is less then and not equal to <instance_B> only then the <instance_C> is given a binary 1 value. If <instance_A> greater than or equal to <instance_B> only then the <instance_C> is given a binary 0 value.

In the second process, the test for less than or equal if <instance_A> is less than or equal to <instance_B> only then the <instance_C> is given a binary 1 value. If <instance_A> greater <instance_B> only then the <instance_C> is given a binary 0 value.

Test for greater than and greater than or equal

These operators check the relationship between given data A and B. In the case of greater than ‘>’, if A is greater than but not equal to B, the result is a boolean true. If A is less than or equal to B, the result is a boolean false.

In the case of test for greater than or equal ‘>=’, if A is greater than or equal to B, the result is a boolean true. If A is less than B, the result is a boolean false. Let us use an ‘if-else’ statement to better understand the application.

<instance_A> <instance_B> --two data instances
    process (check_greaterthan) --greaterthan
       begin 
          if (<instance_A> > <instance_B>) then
          <instance_C> <= '1'; 
          else 
          <instance_C> <= '0'; 
          end if; 
    end process;

<instance_A> <instance_B> --two data instances
    process (check_greaterthan_equal) --greaterthan or equal
       begin
          if (<instance_A> >= <instance_B>) then
          <instance_C> <= '1';
          else
          <instance_C> <= '0';
          end if;
    end process;

The <instance_A>, <instance_B> are data instances of any data type. In the first process, the test for greater than if <instance_A> is greater then and not equal to <instance_B> only then the <instance_C> is given a binary 1 value. If <instance_A> less than or equal to <instance_B> only then the <instance_C> is given a binary 0 value.

In the second process, the test for greater than or equal if <instance_A> is greater than or equal to <instance_B> only then the <instance_C> is given a binary 1 value. If <instance_A> less <instance_B> only then the <instance_C> is given a binary 0 value.

Logical operators

Logical operators perform logic operations between logical array or boolean data. Logical operators in VHDL include:

  • Logical AND  and
  • Logical OR  or
  • Logical NOT of AND  nand
  • Logical NOT of OR  nor
  • Logical Exclusive of OR  xor
  • Logical Exclusive of NOT of OR  xnor

Logical AND

Performs logical AND operation with a logical array or boolean.

<logical_array_storage>  <=  <logical_array> and <logical _array>;
<boolean_storage>  <=  <boolean> and <boolean>;

The and keyword is used to specify an AND between the two elements. The AND operation is performed and stored in their respective <logical_array_storage>  or  <boolean_storage>. You can check out the truth table of the AND operation here.

Logical OR

Performs logical OR operation with a logical array or boolean.

<logical_array_storage>  <=  <logical_array> or <logical _array>;
<boolean_storage>  <=  <boolean> or <boolean>;

The or keyword is used to specify an OR between the two elements. The OR operation is performed and stored in their respective <logical_array_storage>  or  <boolean_storage>. You can check out the truth table of the OR operation here.

Logical NAND

Performs logical NAND operation with a logical array or boolean.

<logical_array_storage>  <=  <logical_array> nand <logical _array>;
<boolean_storage>  <=  <boolean> nand <boolean>;

The nand keyword is used to specify a NAND between the two elements. The nand operation is performed and stored in their respective <logical_array_storage>  or  <boolean_storage>. You can check out the truth table of the NAND operation here.

Logical NOR

Performs logical NOR operation with a logical array or boolean.

<logical_array_storage>  <=  <logical_array> nor <logical _array>;
<boolean_storage>  <=  <boolean> nor <boolean>;

The nor keyword is used to specify a NOR between the two elements. The NOR operation is performed and stored in their respective <logical_array_storage>  or  <boolean_storage>. You can check out the truth table of the NOR operation here.

Logical XOR

Performs logical XOR operation with a logical array or boolean.

<logical_array_storage>  <=  <logical_array> xor <logical _array>;
<boolean_storage>  <=  <boolean> xor <boolean>;

The xor keyword is used to specify an XOR between the two elements. The XOR operation is performed and stored in their respective <logical_array_storage>  or  <boolean_storage>. You can check out the truth table of the XOR operation here.

Logical XNOR

Performs logical OR operation with a logical array or boolean.

<logical_array_storage>  <=  <logical_array> xnor <logical _array>;
<boolean_storage>  <=  <boolean> xnor <boolean>;

The xnor keyword is used to specify an XNOR between the two elements. The XNOR operation is performed and stored in their respective <logical_array_storage>  or  <boolean_storage>. You can check out the truth table of the XNOR operation here.

As you can see, operators in VHDL (or any language for that matter) are easy to use and also very powerful tools. With an increase in the scale of our designs, smart implementation of these operators can help us make our program efficient and save on resources.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.