The creation of any device requires circuits. Complex circuit designing is not an easy task and in the earlier times, engineers had to hand draw each circuit sketch used for creating a project. Computer programming languages have made all our lives easier. Hence, the introduction of Hardware Description Language became a boon to the technology industry. Today, let’s know about Verilog Operators.
HDL enabled faster designing and implementation in the hardware industry. Verilog is the HDL that makes it flexible and user-friendly. Verilog is one of the most popular HDL and they are beneficial.
Dataflow Modeling of Verilog describes combinational circuits in terms of their function rather than gate structure. Dataflow modeling uses operators as their basic structure.
Verilog Data Types
To understand operands and operators, we need to know what are the various Verilog data types.
- Value sets
0 – logic zero.
1 – logic one.
X – unknown value (don’t care).
Z – high impedance state.
- wire
The wire is similar to the physical wire. These are used in gate-level modeling where we use circuit design to write the code. The wire data type cannot store values.
Eg: wire c;
wire [3:0] a;
- wand
The wand is a type of wire. It is called wired AND. The value of the wand is determined by taking the logical AND of the values attached to it.
Eg: wand c;
wand d[7:0];
- wor
It is also a type of wire known as wired-OR. The value of the wand is determined by taking the logical AND of the values attached to it.
Eg:
module comparatorwithwor (input x, input y, output z);
wor p;
assign p = x & y;
assign p = ~x & ~y;
assign z = p;
end module
- reg
Even though the name might be misleading, reg is not exactly a register. It can store values and is used for modeling latches, flip-flops, and memory.
Eg:
reg c;
reg [3:0] d;
- Input
It is the input data type and the input is of a wire type.
Eg:
input a;
input b[3:0];
- Output
It is the output data type. Output can be wire, reg, wand, or wor. By default, it is wire.
Eg:
output x; //wire type output
output reg y[2:0]; //reg type output
- inout
Inout is a bidirectional port and is of wire type.
Eg:
inout a;
inout b[3:0];
- Integer
It is the data type that stores integers. They are used as constants, parameters, and loop indices, and they are of reg type.
Eg:
integer a=10;
Dataflow Modeling
There are three types of modeling for Verilog. They are Dataflow, Gate-level modeling, and behavioral modeling. While the gate-level and dataflow modeling are used for combinatorial circuits, behavioral modeling is used for both sequential and combinatorial circuits.
Dataflow modeling uses expressions instead of gates. Hence, they have operands for generating expressions. Operands can be any data type including constants, integers, real numbers, etc… Operators are used in the operands to provide the desired results. In this article, we will discuss further operators and their various types.
Example
Dataflow modeling of NAND gate
module NAND_2_data_flow (output Y, input A,B);
assign Y = ~(A&B);
end module
Operators: ~, &
Operand: A, B
Verilog Scalar and Vector
For representing a single and a group of bits, Verilog requires scalars and vectors. For example, single-bit flip-flops and 16-bit counters need to be represented.
The declarations reg or net without a specified range is called a scalar. It is considered to be 1 bit wide. Vector is a multibit entity with a specified range.
The expressions in Vector representation are:
MSB: It is the most significant bit which is at the left-most point of the range.
LSB: It is the least significant bit and is the right-hand value of the range.
Operators
As we discussed earlier, there are various types of operators.
Operator types
- Arithmetic Operators
These are basic operators that enable arithmetic functions including addition, subtraction, division, and multiplication. There are two types of arithmetic operators.
- Binary: The binary operators are, add(+), subtract(-), divide(/), multiply(*), power(**), modulus(%).
Suppose a and b are two random integers.
a + b | Adds a and b |
a – b | Subtracts a and b |
a * b | Multiplies a and b |
a / b | Divides a by b |
a ** b | a is raised to the power of b |
a % b | Gives the reminder of a/b |
Eg:
module add32 (a, b, sum);
input [31:0] a,b;
output [31:0] sum;
assign sum = a + b;
end module
- Unary: Unary operators are signs of an operand. They can be (+) or (-).
Eg: -8 //negative 8
+9 //positive 9
- Relational Operator
These operators are used to compare operands. The result will be a 1-bit scalar value. When the relation is true, the result will be 1 and it will be 0 when the relation is false. If there are two unknown operands, the result will be 1.
Operator symbolOperation performed >Greater than<Less than>=Greater than or equal to <=Less than or equal to ==Equality!=Inequality===Case equality !==Case inequality |
Eg: // Compare in 2’s complement; a>b
reg [4:0] x,y;
if (x[4] == y[4]) x[3:0] > y[3:0];
else y[4];
- Bitwise Operators
We can calculate the bit-by-bit results of two operands using this operator.
Operator symbol | Operation performed |
~ | Bitwise Negation |
& | Bitwise AND |
| | Bitwise OR |
^ | Bitwise XOR |
~^ / ~^ | Bitwise XNOR |
Eg:
module and_1 (x, y, z);
input [2:0] x,y;
output [2:0] z;
assign z = x & y;
end module
- Logical operators
They are similar to bitwise operators except that they can be used for single-bit operands. They can treat all the values that are non-zero as 1. These operators are usually used in conditional statements as they work with expressions.
The logical and operator (&&) give the result as 1 or true when both the operands are non-zero. Logical or (||) will give the result as true when at least one of its operands is true. Logical negation (!) turns true operand into false or zero and vice versa. If either of the operands is X, then the result will also be X for both logical or and negation operators.
Operator symbol | Operation performed |
| | Logical Negation |
&& | Logical AND |
|| | Logical OR |
Eg:
wire[9:0] a, b, c; //a and b are multibit variables.
reg k;
if ((a == b) && (c)) k = 1; // k = 1 if a is equal to b, and c is a non-zero number.
else k =! a; // k=0 if a is any non-zero number.
- Shift Operators
Shift operators are used to shifting the operands to right or left. The size of the operand is kept the same by adding zeros to the vacated portions.
There are two types of shift operators:
- Logical shift operators: << and >> – shift the operand and pad with zeros.
- Arithmetic shift operators: <<< and >>> – retains the sign of MSB (useful for numbers with positive or negative sign).
Operator symbol | Operation performed |
<< | Shift left (Logical) |
>> | Shift right (Logical) |
<<< | Shift left (Arithmetic) |
>>> | Shift right (Arithmetic) |
Eg:
Assign c = a<<2; //c=a is shifted by 2 bits. Vacant spaces are filled with zeroes.
- Reduction Operators
Reduction operators are used to reducing the operands to one bit. They can be called the bitwise operators’ unary forms.
Operator symbol | Operation performed |
& | Reduction AND |
| | Reduction OR |
~& | Reduction NAND |
~| | Reduction NOR |
^ | Reduction XOR |
~^ / ^~ | Reduction XNOR |
Eg:
module ck_zero (a, z);
input [2:0] a;
output z;
assign z = ~1 a; //Reduction NOR
end module
- Concatenation Operator
They combine two or more operands. The operand can be a scalar or vector. Its symbol is {}.
Eg:
module Concatenation (a, b, c);
input [3:0] a, b;
output [12:0] c;
parameter d=3’b011;
reg [12:0] c;
always @(a or b)
c={a, b, (2{d}}, 3’b110};
end
end module
- Replication Operator
The replication operator is used to making multiple copies of an item.
Symbol: {n{item}} (n times replication of the item).
Eg:
wire [2:0] x,y; wire [5:0] a;
assign a = {2{ 1’b0}, x}; // Equivalent to a = {0,0,x}
assign b = {2{x}, 3{y}}; // Equivalent to b = {x,x,y,y}
- Conditional Operator
The conditional operator chooses between two expressions concerning the first expression. The first expression is called the condition. If it is 1, the expression chosen will be second and if it is 0, the expression chosen will be third.
Syntax:
(condition) ? (result if condition is true):
(result if the condition is false)
Eg:
assign x = (g) ? a:b;
assign x = (inc = = 2) ? x+1 : x-1;
/* if (inc), x = x+1, else x = x-1 */
?: is also called a ternary operator as it takes 3 operands as inputs. The conditional operator is mainly used for multiplexers as it is the choice of inputs.
Some useful Verilog IDEs
If you are new to Verilog and need to learn the basic programming theories, then there are some Integrated Development Environments (IDE) that you can check out.
- EDA Playground: It is an online IDE suitable for Verilog simulations. You can choose your tools and simulators from dropbox and create codes in various languages. To check out the EDA playground, click HERE.
- Xilinx Vivado: Xilinx vivado is software created by Xilinx exclusively for hardware development languages. It is a free tool and for downloading it, click HERE.
- VerilogCreator: If you are a fan of open-source software, then VerilogCreator is for you. Even though the plugin is under development, almost all major functionalities are available in this version. To find the file format and necessary details, click HERE.
Conclusion
Verilog is an easy and handy hardware programming language developed to handle complex as well as simple circuits. There are various assignments, operators, modeling types, and many other functionalities that enable us to create various necessary circuits using Verilog programming. A clear understanding of all these functionalities and operations is essential to write Verilog codes without errors. Practicing with various IDEs is a good way to learn and make sure to read all the necessary documentation specific to IDEs before working in them.
Frequently Asked Questions
- What are the differences between if-else and the conditional operator?
Conditional Operator | if-else |
Normally used in procedural or continuous assignments. | Normally used within initial or always blocks. |
TRUE and FALSE expressions must be specified. Eg: assign a = (b = = 0) ? c:d;c and d are required expressions. | In the if-else statement, else is optional. Eg: if (en) a = b; //else is not necessary. |
Expressions at both ends of the colon (:) should be single expressions. This means, there should not be any block expressions with begin-end. | Expressions inside if-else can be block code with begin-end. |
The conditional operator cannot be fully trusted when it comes to deeply nested expressions. | For nested expressions, if-else is more suitable as it is easily readable. |
- What is the difference between == and ===?
== cannot be used to compare X’s in a statement. It can only compare 1s and 0s. Hence, the output of == can be 1,0 or X. if either of the input operands is X, the answer for == will be X. While using ===, the output can only be 1 and 0. Thus, it can be used to compare X values.
- What is the difference between Verilog and VHDL?
Verilog is almost similar to the C language and VHDL is similar to ADA language. VHDL is much more complex to learn and write than Verilog. Verilog also supports simple expressions while VHDL does not.
- What are the differences and similarities between logical (<<,>>) and arithmetic(<<<,>>>) shift operators?
Logical left shift, logical right shift, and arithmetic left shift moves the operands to right or left as per the specified units and fills the vacant spaces with 0s. But the arithmetic right shift operator only fills the vacant buts with 0s when the left operand is unsigned. If it is signed, the most significant bit’s sign will be retained.
- What Verilog operator assigns the output of one gate to the input of another?
There is no specific operator that can be used for this. But, we can look at one example code for the half adder.
module Add_half (sum, c_out, a, b);
input a,b;
output sum, c_out;
assign {c_out, sum} = a+b;
end module