Madhava Vemuri, Ph.D.
Verilog is a hardware description language, created in 1984, describing electronic systems. It is a standard language used to describe digital and mixed-signal systems such as field-programmable gate arrays (FPGA) and integrated circuits (ICs). Verilog was first induced into IEEE standard 1364 in 1995 with a latest revision in 2023, with set of keywords to write the specifications. Over the years, Verilog has evolved, and finally, in 2009, the Verilog standard 1364-2009 was merged into the SystemVerilog Language with IEEE Standard P1800-2005, which extended Verilog with an object-oriented design approach and plays a key role in design verification.
The Verilog program is created using a predefined set of reserved words called keyword, which are used to serve as building blocks to describe the behavior of the circuit. These reserved words are defined by the IEEE Standard 1364, which are case sensitive and must be written in lowecase. They provide a syntax for creating digital circuits, define circuit elements, and model the behavior through structural or behavioral modeling. Similar to main function in C program, the Verilog program begins with the keyword module. The module describes the ports of any electrical circuit. To signify the finish of the set statements with a module, the keyword endmodule is written. The names of the ports are written inside the module, next to the identifier within the brackets '(' ')' and always end with a semicolon ';'.
module example(output1, input1, input2, input3);
output [3:0]output1; // notice each statement with the module ends with a semicolon, which signifies the end of each statement
input input1; // represents a single bit port
input input2;
input [1:0]input3; // vector representation for a bus or group of wires
endmodule // Signifies the end of the module
The keywords are reserved word which cannot be used for other naming conventions. The signals, IO ports, entity, architecture names, creating objects (signals, variables) etc. must follow naming conventions. Each name declared is an Identifier to that specific element. The alphanumerical characters are used in creating identifiers, for instance "input1", "input3". Verilog language is case-sensitive,
The following use cases are identified as different variables: input1, iNpUt1, INPUT1.
The underline character __ is significant, and uses cases like are not equivalent: input1,input__1
The identifier cannot start with digit or underline character, use cases like these are not allowed: 1input, _1input, _input1
The identifier can be of any length, but does not allow spaces in between the characters: input_addr_2_reg_is_2_bit_and_how_are_you_doing_2day_
Tips for proper programming style:
Using appropriate naming conventions helps to go with the flow of the specification. Consider the case for Full-Adder, compared to the case (a), case (b) gives a sense into the signal and their behavior
(a)
(b)
Proper indentation increases the readability of the code. It helps to differentiate multiple sections in the program and aligns the comments, signal names etc.
module example(output1, input1, input2, input3);
---> Indicates a tabspace
---> output [3:0]output1;
---> input input1;
---> input input2;
---> input [1:0]input3;
endmodule // Signifies the end of the module, notice there is no semicolon here
Comments increase the readability of the program. Give appropriate comments to the program. Anything written after // is treated as comment in Verilog. Block comments are written using the '/*' , '*/', and anything written between the comments is ignored during the compilation process.
// A single-line comment is written using double forward slash
/*
Statement 1
Statement 2
....
*/
A digital logic circuit can be described in multiple levels of abstraction inside an module block. It can be modelled based on its structural (gate-level), behavioral modelling.
Consider the following example of 2 input AND gate logic
0
0
1
1
0
1
0
1
0
0
0
1
Let us look at each case of modelling Individually.
The behavior modelling is uses the procedural blocks to capture the behavior of the circuit. It uses high-level constructs such as always and initial blocks, conditional statements such as if else case for loops and assignment operators such as =, <=.
To identify the other variables within the module, keywords such as wire, reg are used. They can used to create multiple datatypes such as scalar and vector.
module example(out1, in1, in2);
// static initialization examples using
reg x1,x2;
wire w1, w2, w3;
// vector initialization examples using
reg [1:0]x1,x2;
wire w1, w2, w3;
endmodule
There are 8 gate primitives in Verilog that can be used to describe the gate. To instantiate the gate, an identifier is used, which is written next to the primitive. The input and output ports of the gate are specified next to the identifier. These gates except buf, not can only drive one bit output, and can have multiple inputs of multiple data types, such as scalar and vector. In the case of latter, they can drive multiple outputs, but has only one bit input and must be of single scalar datatype.
and
or
nand
nor
xor
buf
not
and and1(out1, in1, in2, in3,...)
or or1(out1, in1, in2, in3,...)
nand nand1(out1, in1, in2, in3,...)
nor nor1(out1, in1, in2, in3,...)
xor xor1(out1, in1, in2, in3,...)
buf buf1(out1, out2, out3,..., in1)
not not1(out1, out2, out3,..., in1)