8.0 Verilog: An Alternative HDL
8.1 Introduction to Verilog
Verilog is another prominent Hardware Description Language (HDL) used to describe and model digital electronic systems. It provides a way to design, simulate, and synthesize circuits in a manner that is independent of any specific fabrication technology. Verilog is particularly valued for its concise syntax and its efficiency in designing and debugging large, complex circuits.
Verilog supports design at multiple levels of abstraction, allowing designers to move between high-level concepts and low-level implementations. The three major levels are:
- Behavioral Level: This is the highest level of abstraction, where a system is described using concurrent and sequential algorithms. It focuses on the functional behavior of the design using constructs like functions, tasks, and procedural blocks, without regard to the underlying hardware structure.
- Register-Transfer Level (RTL): This level describes the circuit in terms of the flow of data between registers and the logical operations performed on that data. The modern definition of RTL has expanded to encompass any Verilog code that is synthesizable into hardware by EDA tools.
- Gate Level: This is the lowest level of abstraction, where a system is described as a netlist of interconnected logic gates and predefined primitives. All signals are discrete and have definite logical values (0, 1, X, Z).
Like any language, Verilog has a set of lexical rules. Its basic tokens include:
- White Space: Spaces, tabs, and newlines are used to separate tokens and are otherwise ignored.
- Comments: Single-line comments begin with //, and multi-line comments are enclosed in /* … */.
- Numbers: Numbers can be specified in binary, octal, decimal, or hexadecimal using the syntax <size>'<radix><value> (e.g., 8’hFF).
- Identifiers: Names given to objects like modules or registers. They must begin with a letter or underscore and are case-sensitive.
- Keywords: Reserved words with special meaning, such as module, reg, wire, and always. All keywords are in lower case.
We will begin our exploration of Verilog with its lowest level of abstraction: gate-level modeling.
8.2 Gate-Level Modeling and Data Types
Verilog provides a set of built-in primitives that represent basic logic gates (e.g., and, or, xor), transmission gates, and switches. While not typically used for initial design work (which is done at the RTL level), these primitives are crucial for modeling the cells in an ASIC/FPGA library and for post-synthesis simulation.
Gate-level modeling exposes two key physical properties of hardware:
- Drive Strength: Defines the strength of a gate’s output, representing its ability to source or sink current.
- Delays: Represents the propagation delay of a gate, which can be specified for rising and falling output transitions.
To construct models, Verilog uses a set of fundamental data types:
- Value Set: Verilog uses a four-state logic system:
- 0: Logic zero or a false condition.
- 1: Logic one or a true condition.
- x: An unknown or uninitialized logic value.
- z: A high-impedance state, representing a disconnected wire.
- Nets (wire, wand, wor, tri): A wire represents a physical connection between components. It cannot store a value and must be continuously driven by a gate or an assign statement. Specialized net types like wand (wired-AND) and wor (wired-OR) are used to model specific wiring behaviors.
- Registers (reg): A reg is a data object that holds a value between procedural assignments. It is used to model memory elements like flip-flops and latches. Despite its name, a reg does not always synthesize to a physical register; it can also represent the input to a combinational logic block within a procedural context.
- Ports (input, output, inout): These declare the direction of module ports. input and inout ports are of net type (wire), while output ports can be declared as wire or reg.
- Other Data Types:
- integer: A 32-bit signed variable of type reg.
- supply0/supply1: Nets tied to logic 0 (ground) and logic 1 (power).
- time: A 64-bit unsigned variable used for simulation time.
- parameter: A constant value that can be customized at module instantiation.
These data types are manipulated using a rich set of operators.
8.3 Verilog Operators and Operands
Verilog includes a comprehensive set of C-like operators for manipulating data.
| Operator Category | Operators |
| Arithmetic | +, -, *, /, % |
| Relational | ==, !=, >, >=, <, <= |
| Bit-wise | &, ` |
| Logical | !, &&, ` |
| Reduction | &, ` |
| Shift | <<, >> |
| Concatenation | { } |
| Replication | {n{item}} |
| Conditional | ? : |
- Arithmetic Operators perform standard math operations. Example: h = b + d;
- Relational Operators compare two operands and return a 1-bit true (1) or false (0) result. Example: if (z == y) c = 1;
- Bit-wise Operators perform a bit-by-bit comparison between two operands. Example: assign c = d & b;
- Logical Operators operate on logical values (treating non-zero as true) and return a 1-bit true or false. Example: if ((a == b) && (c))
- Reduction Operators are unary operators that perform a bit-wise operation on all bits of a single vector operand, returning a 1-bit result. Example: assign z = &x; (ANDs all bits of x together).
- Shift Operators shift a vector left or right by a specified number of bits. Example: assign z = c << 3;
- Concatenation Operator combines multiple operands into a single, larger vector. Example: assign x = {1’b0, a};
- Replication Operator makes multiple copies of an item. The replication operator {n{item}} creates n copies of an item. For example, assign x = {2{1’b0}, a}; would concatenate two copies of 1’b0 with the vector a, resulting in a new vector equivalent to {0, 0, a}.
- Conditional Operator acts as a multiplexer, choosing between two expressions based on a condition. Example: assign x = (g) ? a : b;
These operators work on various types of operands:
- Literals: Constant values, either numeric (4’b1010) or string (“hello”).
- Wires, Regs, and Parameters: The data types themselves.
- Bit-Selects and Part-Selects: A single bit (x[2]) or a range of bits (x[4:2]) from a vector.
- Function Calls: The return value from a function.
These operators and data types are used within the principal design entity in Verilog: the module.
8.4 Modules and Behavioral Modeling
The Module is the fundamental building block in Verilog. A module declaration defines its name and its list of ports. Within a module, logic can be described using a combination of continuous assignments, procedural blocks, and module instantiations.
- Continuous Assignments: These are used to model combinational logic. Using the assign keyword, a net variable (like a wire) is continuously driven by the value of an expression. Any change in the right-hand side expression immediately reflects on the left-hand side net.
- Procedural Assignments: These are used for updating reg variables and occur within procedural blocks.
There are two main procedural blocks:
- initial block: Executes exactly once at the beginning of the simulation. It is typically used for initialization and test stimulus generation.
- always block: Executes repetitively. Its execution is triggered by a sensitivity list, which specifies the events (e.g., signal changes) that cause the block to re-evaluate.
Within these blocks, assignments to reg variables can be one of two types:
- Blocking Assignments (=): These are executed sequentially. An assignment must be completed before the next statement in the block can be executed. This is useful for modeling sequential algorithms.
- Non-blocking Assignments (<=): All right-hand side expressions are evaluated at the beginning of the time step, and the assignments are scheduled to occur at the end of the time step. This allows for parallel execution semantics, which is crucial for accurately modeling synchronous hardware like registers that all update on the same clock edge.
Behavioral models use a variety of control flow statements inside procedural blocks:
- Conditional Statements: if-else for simple branching and case for multi-way branching.
- Looping Statements: forever, repeat, while, and for provide ways to execute statements multiple times.
Execution within procedural blocks is managed by Timing Controls:
- Delay Control (#): Delays execution by a specified number of simulation time units (e.g., #10).
- Event Control (@): Suspends execution until a specified event occurs, such as a value change in a signal (@(data)) or a specific clock edge (@(posedge clk)).
In conclusion, both VHDL and Verilog are powerful and indispensable tools for the modern VLSI designer. They provide the necessary levels of abstraction to describe, simulate, and ultimately synthesize the complex digital circuits that power our world, enabling the creation of systems that would be impossible to design at the transistor level alone.