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.
Contents
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:
- Number of Operands
- Operation
Operators in Verilog based on the number of operands
Depending on how many operands are used in an expression, operators are classified as:
- Unary
- Binary
- 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
-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 |
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.
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.