View Course Path

Operators in Verilog

Verilog deals with the design of digital electronic circuits.  Describing a complex circuit in terms of gates (gate-level modeling) is a tedious task. Thus, we use a higher level of abstraction. This modeling, one above the gate-level, is known as dataflow modeling. In this level, we describe the flow of data from input to output.

To do this, dataflow modeling occasionally uses expressions, operands, and operators to describe an electronic circuit. For example, if we consider the dataflow model of an AND gate:

module and_gate(a,b,out);
input a,b;
output out;

assign out = a & b;
endmodule

From the above code, we can see that it consists of an expression a & b with two operands a and b and an operator &.

In this article, we are we will be looking at all the operators in Verilog. We will be using almost all of these Verilog operators extensively throughout this Verilog course. The application of these operators will allow you to internalize their use-case scenarios and syntax.

Operators in Verilog

An operator, in many ways, is similar to a simple mathematical operator. They receive one or two inputs and generate a single output. Operators enable synthesis tools to choose the desired hardware elements.

We can categorize operators based on:

  1. Number of Operands
  2. Operation

Operators in Verilog based on the number of operands

Depending on how many operands are used in an expression, operators are classified as:

  1. Unary
  2. Binary
  3. Ternary

Unary operators

Unary operators need only one operand. For example, arithmetic operators for representing sign (+,-), negation operator (!,~), reduction operator (&, |, ~, ^).

Binary operators

A binary operator requires two operands to perform operations. The majority of the operators available in Verilog requires two operands. Addition, logic operations, multiplication, etc.

Ternary operators

Ternary operators require three operands. For example, conditional operator(? :).

We will look at examples for each of the above in detail as we proceed.

Operators in Verilog based on Operation

We can also classify operators based on what operation they perform on given data.

Arithmetic operators

This operator is gonna take us to good old school days.

5+2 = 7 // addition
6-4 = 2 // subtraction
2*3 = 6 // multiplication
20/5 = 4 // division

Arithmetic operators are used to perform basic math calculations. They perform a specific operation on two numeric values and return a single numeric value.

Arithmetic operators play a significant part in describing hardware units such as Arithmetic logic Unit (ALU). Therefore, Verilog has provided us with the following arithmetic operators.

Expression Operator used Operation performed
a + b + Add
a – b Subtract
a * b * Multiply
a / b / Divide
a % b % Modulus(the remainder is given as result)
a ** b ** Power(exponent)

What about signed numbers?

Verilog also has the provision for representing signed numbers. We use ‘+’ and ‘-‘ to represent positive and negative numbers. In short, ‘+’ and ‘-‘ can be used in both unary and binary form. Unary is for representing signed number and binary for calculations.

//unary arithmetics
-4 // negative number
+5 // positive number
//binary arithmetics
5+4 // addition
6-4 // subtraction
Note: It is advisable to write negative numbers in real or integer format. Since Verilog converts negative numbers into 2’s complement internally, writing in <size>'<base><number> format will yield incorrect result.
-10/5 // yield correct result
- 32'd10/5 // will yield incorrect result

Now that we have an idea of what arithmetic operators are, we can see how they are used in Verilog using a sample program as an example.

module arithmetic_operations;

reg[7:0] data1;
reg[7:0] data2;

initial
begin

data1 = 45;
data2 = 9;
$display ("add(data1,data2) = %d", data1 + data2)
$display ("subtract(data1,data2) = %d", data1 - data2);
$display ("multiply(data1,data2) = %d", data1 * data2);
$display ("divide(data1,data2) = %d", data1 / data2);
$display ("modulus(data1,data2) = %d", data1 % data2);
$display ("power(data2,2) = %d", data2 ** 2);

end
endmodule

Simulation log

add(data1,data2) = 54
subtract(data1,data2) = 36
multiply(data1,data2) = 149
divide(data1,data2) = 5
modulus(data1,data2) = 0
power(data2,2) = 81

Logical Operators

Logical operators perform a logical operation on the logical value of the operands and tell you whether it is true or false, i.e., it returns a boolean value. For example:

Let’s say we have to perform logical and operation between 3 (non-zero) and 0 (zero). Hence, Logical value of 3 is true(1) and for 0, it is false(0). Therefore, AND of true and false will give you false (0).

These are the logical operators available in Verilog.

Expression Operator Operation Description
A && B && Logical – and The result will be 1 (true ) if A and B are true
A || B || Logical – or The result will be true if either A or B is true
!A ! Logical negation Will convert to zero if A is non-zero or 1 A is   zero or false value

Here’s how Verilog performs logical operations.

module logical_operation;
reg[7:0] A;
reg[7:0] B;
reg[1:0] din1;
reg[1:0] din2;
wire out;
initial
begin
A = 3;
B=0;
din1 = 2’b0x;
din2 = 2’b10
$display(“logical_AND(A,B)=%b”, A &&B); // Equivalent to logical-1 && logical-0
$display(“logical_OR(A,B)= %b“, A ||B); // Equivalent to logical-1 || logical-0
$display(“logical_NOT(A) = %b“, !A); // Equivalent to not(logical-1)
$display(“logical_NOT(B) = %b“, !B); // Equivalent to not(logical-0)
$display(“logical_AND(din1,din2) = %b“, din1 &&din2); // Equivalent to ( x && logical-1)
$display(“out = %b“, (A==2)&&(B==3); // Evaluates 1 if both A=2 and B=3 are true otherwise false.
end
endmodule

Simulation log

logical_AND(A,B) = 0
logical_OR(A,B) = 1
logical_NOT(A) = 0
logical_NOT(B) = 1
logical_AND(din1,din2) = x;
out = 0

Bit-wise Operators

Verilog supports the use of a bit-wise operator. This operator is a bit of an odd cross between a logical operator and an arithmetic operator. They take each bit in one operand and perform the operation with the corresponding bit in the other operand. If one of the operands is shorter than the other, the length will be made the same by adding zeros on the shorter operand. It’s a bit confusing. Check out the example below.

For example: bitwise AND of a = 3(11) and b=2 (00). Bitwise AND is similar to concatenating a[1] & b[1] and a[0] & b[0]  which gives a result 00.

We will get a better understanding when we go through the simulated output of this code.

module bitwise_logical_operations;
reg[3:0] X, Y, Z;

initial
begin

X=4’b1010;
Y=4’b1101;
Z=4’b10x1;

$display (“~X = %b“, ~X); // Negation
$display (“X & Y = %b“, X & Y); // Bitwise AND
$display (“X | Y = %b“, X | Y); // Bitwise OR
$display (“X ^ Y = %b“, X ^ Y); // Bitwise XOR
$display (“X ^~ Y = %b“, X ^~ Y); // Bitwise XNOR
$display (“X & Z = %b“, X & Z); // Bitwise AND

end
endmodule

Simulation log

~X = 0101
X & Y = 1000
X | Y = 1111
X ^ Y = 0111
X ^~ Y = 1000
X & Z = 10x0

Reduction Operators

Unlike logical and bitwise logical operators, the Reduction operator is a unary operator. This operand is useful for converting a multi-bit vector into a single bit scalar value. It performs bit by bit logical operation on the vector operand and returns a boolean value.

For example,

&(1011) = 1 & 0 & 1 & 1 = 0 // reduction and of 1011

Verilog has provided us with the following types of reduction operators.

Expression Operator Description
&A & Performs bitwise AND operation on A
|A | Performs bitwise OR operation on A
^A ^ Performs bitwise XOR operation on A
Note: reduction NAND, reduction NOR and reduction XNOR are performed by inverting results of reduction AND, reduction OR and reduction NOT respectively.

Here’s the code for understanding how reduction operator is described in Verilog

module reduction_operators;
reg[5:0] X;
initial
begin
X = 4'b1010;
$display ("&X = %b", &X);
$display ("|X = %b", |X);
$display ("^X= %b", ^X);
$display("~^X = %b", ~(^X)); //XNOR of X
 
end
endmodule

Simulation log

&X = 0
|X = 1
^X= 0
~^X = 0

Difference between logical, bitwise logical, and reduction operators?

Logical Bitwise logical Reduction
Binary operator (except negation) Binary operator (except negation) Unary operator
Returns a 1-bit Boolean value The return value is of the same size as the operands Returns a 1-bit Boolean value
Evaluate the logical values of the operands and then perform a logical operation. Performs a logical operation on each bit of operand with the corresponding bit of other operands Evaluate each bit of vector operand and convert it into a scalar by performing a logical operation.

In short, even though the functionalities look similar, there is a difference in how the above operators perform on the operands.

Relational operators

If we want to check the relation between the given operands, then we use relational operators. Relational operators test the relation between operands and return a 1 or 0.

Expression Operator Description
a>b < (greater than) Returns 1 if a is greater than b
a<b < (less than) Returns 1 if a is less than b
a<=b <= (less than or equal to) Returns 1 if a is either less than or equal to b
a>=b >= (greater than or equal to) Returns 1 if a is either greater than or equal to b

An example code will help us to understand how relational operators work in Verilog.

module relational_operation;
reg[7:0] A;
reg[7:0] B;
reg[5:0] X;
reg[5:0] Y;
reg[5:0] Z;

initial
begin

A = 3;
B=4;

X = 4’b1010;
Y = 4’b1101;
Z = 4’b1xxx;

$display(“Is A less than or equal to B = %b”, A<=B);
$display(“Is A greater than B = %b”, A>B);
$display(“Is Y greater than or equal to X = %b”, Y>=X);
$display(“Is A less than or equal to B = %b”, A<=B);
$display(“Is Y less than Z = %b”, Y<Z);
end
endmodule

Simulation log

Is A less than or equal to B = 1
Is A greater than B = 0
Is A less than or equal to X = 1
Is Y less than Z = x

Equality Operator

Like Relational operators, Equality operators are also used for relation checking. These operators test whether the operands are the same or not. They return 1 if both the operands are the same and 0 if they are not.

A list of equality operators in Verilog is given below.

Expression Operator Description
A = = B = = A equal to B, result is unknown if a or b has z(high impedance) or x(unknown)
A != B ! = A not equal to B, result is unknown if a or b has z(high impedance) or x(unknown)
A = = = B = = = A equal to B including x(unknown) and z(high impedance)
A ! = = B ! = = A not equal to B including x(unknown) and z(high impedance)

As per the table, we can see that there are two types of equality operators:

  • Logical Equality (==,!==): In this case, if one of the operand bits has an x(unknown) or z(high impedance), the resultant will be x.
  • Case Equality (===,!===): Here, the x(unknown) and z(high impedance) in operand bits are included during the comparison. So the result will be either true (1) or false (0).

Let’s see how Verilog performs equality operation with the help of the code below:

module equality_operators;
reg[7:0] A;
reg[7:0] B;
reg[5:0] M;
reg[5:0] N;
reg[5:0] X;
reg[5:0] Y;
reg[5:0] Z;

initial
begin

A = 3;
B=4;
X = 4’b1010;
Y = 4’b1101;
Z = 4’b1010;
M = 4’b1xxz;
N = 4’b1xxx;

$display (“Is A equal to B = %b”, A == B);
$display (“Is X not equal to Y = %b”, X != Y);
$display (“Is A equal to B = %b”, A == B)
$display (“Is Z equal to M = %b”, Z === M);
$display (“Is Z equal to N = %b”, Z === N)
$display (“Is M not equal to N = %b”, M !== N);

end
endmodule

Simulation log

Is A equal to B = 0
Is X not equal to Y = 1
Is A equal to B = 0
Is Z equal to M = 0
Is Z equal to N = 0
Is M not equal to N = 1

Shift Operators

Shift operators are used to shift data in a variable. This operator is essential for modeling hardware elements like shift registers, shift and add multipliers, etc.

There are two types of shift operations:

  • Logical shift: they shift the input and pad with zeros. For example, shift 1000 right twice will result in 0010.
  • Arithmetic shift: they preserve the sign of MSB of our variable we need to shift. For example, arithmetic shift 1000 to the right twice will be 1110.

The shift operators provided in Verilog are:

Operator Description
>> Right shift
<< Left Shift
>>> Arithmetic Right Shift
<<< Arithmetic Left shift

We will be able to gain a clear understanding of how a shift operator works in Verilog from the below code:

module shift_operators;

reg [3:0] var1 = 4'b1000;
reg signed [3:0] var2 = 4'b1000
initial 
begin

//left shift
$display("%b", var1 <<  1);
$display("%b", $signed(var1) <<< 1); // Cast as signed
$display("%b", var2 <<< 1);          // Declared as signed type

 // Right Shift
$display("%b", var1 >>  2);
$display("%b", $signed(var1) >>> 2); // Cast as signed
$display("%b", var2 >>> 2) ;         // Declared as signed type
end
endmodule

Simulation log

0000
0000
0000
0010
1110
1110

Concatenation Operators

Concatenation operators are used to join different bits of data into one. Concatenations are expressed using the brace characters { }, with commas separating the expressions within.

We will get a better understanding of the working of the concatenation operator from the simulated output of the code below.

module concatenation_operator;
reg A;
reg[1:0] B, C;
reg[2:0] D;
initial
begin
A = 1'b1;
B= 2'b00;
C = 2'b10;
D = 3'b110;
$display ("concatenation(B,C) = %b", {B,C}); // two 2 bits joined to form 4 bit number
$display ("concatenation(A,B,C,D,3'b001) = %b", {A,B,C,D,3'b001});
$display ("concatenation(A,B[0],C[1]) = %b", {A,B[0],C[1]});
end
endmodule

Simulation log

concatenation(B,C) = 0010
concatenation(A,B,C,D,3'b001) = 10010110001
concatenation(A,B[0],C[1]) = 101

Replication operator

The replication operator is used to replicate a group of bits n times. It takes the format {n{m}}, where n indicates replication multiplier i.e., how many times m should be repeated.

For example, in {3{2’b01}} 3 is the repetition multiplier and 2’b01 is what will be replicated 3 times.

It is important to note that the repetition multiplier must be a constant.

Look at the Verilog code and simulated output below to see how the replication operator works.

module replication_operator;
reg A;
reg[1:0] B, C;
reg[2:0] D;
wire Y;
initial
begin
A = 1'b1;
B= 2'b00;
C = 2'b10;
D = 3'b110;
$display ("replicating A = %b", {4{A}});
$display ("replicating A and B = %b", {{4{A}},{2{B}}});
$display ("replicating A,B,C = %b", {{4{A}},{2{B}},{C}});
end
endmodule

Simulation log

replicating A = 1111
replicating A and B = 11110000
replicating A,B,C = 1111000010

Conditional Operator

The conditional operator selects an expression for evaluation depending on the value of the condition.

condition?true_expression:false_expression

If the condition is evaluated as false (or zero value), then false_expression is evaluated and used as a result of an entire expression.

For example

assign out = enable?data1:data2;

The above statement means that out will be assigned data1 if enable is true(1) or zero if enable is false(0).

Verilog makes use of the conditional operator in order to build tri-state buffers and multiplexers.

Let’s see how the conditional operator can be used practically.

module conditional;
reg  check = 1'b1;
wire out;
assign out = check  ? 1'b1  : 1'b0;
initial 
begin
 #1;   
$display("OUTPUT: %s", check ? "HI THERE" : "POTATO");
$display("Value of out: %b", out);
$display("%h", (10 > 5) ? 16'hABCD : 16'h1234);
$display("%s", (1 == 1) ? "YES, ONE EQUALS ONE" : "HOW DID YOU GET HERE");
end
endmodule

Simulation log

OUTPUT: HI THERE
 Value of out: 1
abcd
YES, ONE EQUALS ONE

Operator Precedence in Verilog

We have discussed the different operators that we can use in Verilog. Is it possible to use multiple operators in a single expression?  Undoubtedly, yes. Then how do we choose which operation to perform first?

That is when the operator precedence table comes to play.

This table describes the order in which the operators are executed.

Precedence Operators Operator Symbols
Highest Unary

Multiply Divide, Modulus

+ – ! ~

* / %

Add Subtract

Shift

+ –

<< >>

Relational

Equality

< <= > >=

== !== === !===

Reduction

 

 

Logical

& ~&

^ ^~

| ~|

&&

||

Lowest Conditional ?:

For example:

A && B || C && D // same as (A && B) || (C&&D) expression in parenthesis evaluated first

But, it is better to use brackets rather than depending entirely on the precedence of operators. This will ensure the readability of the expression and correctness of the result.

Tabular summary

So, we have gone through all the operators that Verilog has provided. Let’s summarize the operators that we have learned.

Operator Type Operator Symbol Operation performed Number of operands
Arithmetic * Multiply Two
/ Divide Two
+ Add Two
Subtract Two
% Modulus Two
** Power(exponent) Two
Logical ! Logical negation One
&& Logical and Two
|| Logical or Two
^ Logical xor Two
Relational > Greater than Two
< Less than Two
>= Greater than or equal to Two
<= Less than or equal to Two
Equality == Equality Two
!= Inequality Two
=== Case equality Two
!=== Case inequality Two
Bit-wise ~ Bit-wise negation One
& Bit-wise and Two
| Bit-wise or Two
^ Bit-wise xor Two
^~ Bit-wise xnor Two
Reduction & Reduction and One
~& Reduction nand One
| Reduction or One
~| Reduction nor One
^ Reduction xor One
~^ Reduction xnor One
Shift >> Right shift Two
<< Left shift Two
>>> Arithmetic right shift Two
<<< Arithmetic left shift Two
Concatenation {} concatenation Any number
Replication {{}} Replication Any number
Conditional ?: Conditional Three

Keep the summary table of the Verilog operators above handy. Operators are like tools that help you implement your logic. If you ever feel stuck, take a glance at your tools and they might offer you a way out of your logical quandary.