By John

May 21, 2021

In this post, we talk about the different operators which we can use in SystemVerilog. These operators provide us with a way to process the digital data in our verilog designs.

This processing can be extremely simple, as is the case with simple logic gates. However, we may also need to perform complex logical or mathematical operations on our data.

In any case, SystemVerilog provides us with a number of operators which allow us to perform a wide range of different calculations or operations on our data.

In most instances when we use SystemVerilog operators, we create boolean expressions or logic circuits which we want to synthesize. However, there are also some operators which we can't use to write synthesizable code.

The SystemVerilog operators are entirely inherited from verilog. Therefore, if you are already familiar with verilog it is not necessary to read this post.

Let's take a closer look at the various different types of operator which we can use in our SystemVerilog code.

We use the bit wise operators to combine a number of single bit inputs into a single bit output. In addition.

We most commonly use the bit wise operators to model logic gates in SystemVerilog.

The table below shows the full list of bit wise operators which we can use in SystemVerilog.

SystemVerilog Bit Wise Operators | ||
---|---|---|

Operator | Description | |

~ | bit-wise NOT | |

& | bit-wise AND | |

~& | bit-wise NAND | |

| | bit-wise OR | |

~| | bit-wise NOR | |

^ | bit-wise XOR | |

~^ | bit-wise XNOR |

The SystemVerilog code below shows how we use each of these operators in practise.

```
// Returns the value not a
y = ~a;
// Returns the value of a and b
y = a & b;
// Returns the value of a or b
y = a | b;
// Returns the value of a nor b
y = a ~| b;
// Returns the value of a nand b
y = a ~& b;
// Returns the value of a xor b
y = a ^ b;
// returns the value of a xnor b
y = a ~| b;
```

We have seen in the previous section how we can use the bitwise operators to combine 2 or more single bit inputs.

However, we can also use the bit wise operators on SystemVerilog vector types to reduce them to a single bit.

When we do this, we pass only the name of the vector that we want to reduce preceded by the operator.

All of the bits in the vector are then reduced to a single bit by applying the relevant logical operation to them.

For example, if we had a 2 bit vector and applied the and reduction operation, the result would be an and of the 2 bits in the vector.

When we use the bit wise operators in this way, they are commonly referred to as reduction operators.

The code snippet below shows how we use the reduction operators in practice. We can also simulate these examples on EDA playground.

```
// Returns the and reduction of vector a
y = & a;
// Returns the or reduction of vector a
y = | a;
// Returns the nor reduction of vector a
y = ~| a;
// Returns the nand reduction of vector a
y = ~& a;
// Returns the xor reduction of vector a
y = ^a;
// Returns the xnor reduction of vector a
y = ~| a;
```

As we can see from this, we can use all of the bit wise operators except for the not operator to perform vector reductions.

We use arithmetic operators to perform basic mathematic functions on our variables. These operators should already be familiar as they are mostly replications of common mathematic symbols.

However, these operators also require some consideration when we use them with synthesizable code.

The plus, minus and multiplication operators can all be synthesised by most modern tools.

However, this can often result in sub-optimal logical performance. As a result, it can be necessary to design logic circuits which specifically perform these functions.

Alternatively, we may wish to use DSP blocks within our FPGA to perform these operations more efficiently.

We should never use the modulus, exponential or divide operators for synthesizable code as most tools will be unable to handle them.

The table below shows the full list of arithmetic operators in SystemVerilog.

SystemVerilog Arithemtic Operators | ||
---|---|---|

Operator | Description | |

+ | addition | |

- | subtraction | |

* | multiplication | |

/ | division | |

% | modulus | |

** | Exponential operator |

The code snippet below shows how we use each of these operators in practise.

```
// Returns the value of a plus b
y = a + b;
// Returns the value of a minus b
y = a - b;
// Returns the value of a multiplied by b
y = a * b;
// Returns the value of a divided by b
y = a / b;
// Returns the modulus of a divided by b
y = a % b;
// Returns a to the power of b
y = a ** b;
```

We use relational operators to compare the value of two different variables in SystemVerilog. The result of this comparison returns either a logical 1 or 0, representing true and false respectively.

These operators are similar to what we would see in other programming languages such as C or Java.

In addition to this, most of these operators are also commonly used in basic mathematics expressions so they should already feel familiar.

The table below shows the full list of relational operators in SystemVerilog.

SystemVerilog Relational Operators | ||
---|---|---|

Operator | Description | |

> | greater than | |

>= | greater than or equal to | |

< | less than | |

<= | less than or equal to | |

== | is equal to | |

!= | is not equal to |

The SystemVerilog code below shows how we use each of the relational operators in practise.

```
// 1 if a is greater than b
y = a > b;
// 1 if a is greater than or equal to b
y = a >= b;
// 1 if a is less than b
y = a < b;
// 1 if a is less than or equal to b
y = a <= b;
// 1 if a is equal to b
y = a == b;
// 1 if a is not equal to b
y = a != b;
```

The SystemVerilog logical operators are similar to the bit-wise operators we have already seen.

However, rather than using these operators to model gates we use them to combine relational operators. As a result, we can build more complex expressions which can perform more than one comparison.

As with relational operators, these expressions return either a 1 (true) or 0 (false).

There are only three logical operators which we can use in SystemVerilog. Again, these are similar to operators which are used in languages such as C or Java.

The table below shows the full list of logical operators in SystemVerilog.

SystemVerilog Logical Operators | ||
---|---|---|

Operator | Description | |

&& | logical AND | |

|| | logical OR | |

! | logical NOT |

The SystemVerilog code below shows how we use each of the logical operators in practise.

Again, it is important that we use parentheses to separate the different elements in our expressions when using these operators.

```
// Returns 1 if a equals b and c equals d
y = (a == b) && (c == d);
// Returns 1 if a equals b or a equals c
y = (a == b) || (a == c);
// Returns 1 if a is equal to b
y = !(a == b);
```

In addition to the operators we have already seen, there are a few extra operators which we can use for specific logical functions.

One of the most useful and commonly used of these special functions are the shift operators, which are shown in the table below.

SystemVerilog Shift Operators | ||
---|---|---|

Operator | Description | |

<< | shift left logical | |

>> | shift right logical | |

<<< | shift left arithmetic (introduced in verilog 2001) | |

>>> | shift right arithmetic (introduced in verilog 2001) |

When designing digital circuits, we frequently make use of shift operations. As a result, SystemVerilog provides us with a simple technique for implementing these functions.

The shift operator actually requires two arguments. The first of these is the name of the signal which we want to shift. The second argument is the number of bits we want to shift.

When we use the logical shift operators, all the blank positions are filled with 0b after the signal has been shifted by the required number of bits.

In contrast, the arithmetic shift operators preserve the sign of the shifted signal. As a result of this, they should only be used with signed data types.

The code snippet below shows how we use the shift operators in practise.

```
// Shift the a signal left by 3 bits
a = a << 3;
// Shift the b signal right by 8 bits
b = b >> 8;
// Shift the a signal left by 2 bits using arithmetic operator
// In this instance we use casting to make c a signed type
c = $signed(c) <<< 3;
// Shift the d signal right by 5 bits using arithmetic shift operator
// In this instance we assume d is already a signed type
d = d >>> 5;
```

In SystemVerilog, we use a construct known as the conditional operator to assign data to a signal based on a conditional statement.

To use the conditional operator, we write a logical expression before the ? operator which is then evaluated to see if it is true or false.

The output is assigned to one of two values depending on whether the expression is true or false.

This operator may already be familiar as it is also used in other programming languages such as C and Java. However, in this case it is known as the ternary operator.

The code snippet below shows the general syntax for the SystemVerilog conditional operator.

```
output = <condition> ? <true> : <false>
```

When the expression given in the <condition> field evaluates as true, then the output is set to the value given in the <true> field.

If the conditional expression evaluates as false, then the output is set to the value given by the <false> field.

The code snippet below shows a practical example of the SystemVerilog conditional operator. In the a future post in this series, we see how we can use the conditional operator model multiplexors.

```
// Assign a to the value of c when it is greater than b
a = c > b ? c : b;
```

The final types of SystemVerilog operator which we can use are the concatenation and replication operators.

In both instances, the output of these operators are a vector type. However, the inputs to both of these operators can be either single bit or vector types.

Both of these SystemVerilog operators are shown in the table below.

SystemVerilog Concatenation Operator | ||
---|---|---|

Operator | Description | |

{ } | Concatenation operator | |

{{ }} | Replication operator |

We use the SystemVerilog concatenation operator to combine two or more signals into a vector.

As an example, we may have 2 single bit signals which we want to combine to use as an address for a multiplexor.

To use the concatenation operator, we list the signals which we wish to combine within the curly brackets. We separate this list of signals using a comma.

When we use the SystemVerilog concatenation operator, the bits in the output match the order in which they are listed inside the brackets.

For example, the code snippet below would result in a output vector which has the value 0011b.

```
c ={ 2'b00, 2'11};
```

We use the replication operator to assign the same value to a number of bits in a vector.

For example, if we wanted to assign all of the bits of a vector to 0b then we would use the replication operator.

When we use the replication operator we have to specify both the signal or value we want to replicate and the number of times we want to replicate it.

The SystemVerilog code below show how we use the concatenation and replication operators in practice.

```
// Combine the signal a and b into a vector using concatenation
c = {a, b};
// Replicate signal c 3 times
d = { 3{c} };
```

Enjoyed this post? Why not share it with others.

Join our mailing list and be the first to hear about our latest FPGA tutorials

Sign Up to our Mailing List© 2024 FPGA Tutorial