1. Basic Concepts
Verilog HDL, which stands for Verilog Hardware Description Language, supports design from high-level abstraction down to the transistor level. It uses a hierarchy of modules to represent extremely complex digital systems. EDA tools convert modules into a netlist, which is then implemented in physical circuits using FPGA or ASIC technologies.
Another well-known hardware description language is VHDL, which is more oriented toward standardization.
The descriptive capabilities of the two languages differ slightly. Verilog’s system-level abstraction ability is somewhat weaker, but its descriptive power at the gate and switch levels is stronger than that of VHDL.
The mainstream design methodology is RTL design, where a netlist is generated from RTL descriptions. Behavioral synthesis tools also allow direct descriptions of circuit algorithms and behavior.
2. Design Flow and General Design Methodologies
2.1 Typical Project Design Flow
(1) Design Specification
This consists of a detailed definition of the project’s design requirements:
- System block diagram showing the relationship between the chip and the system: system description.
- Internal block diagram illustrating the functionality of each part: functional description.
- Description of IO pins: pin description.
- Timing estimation: timing description.
- Estimate of the number of device gates: area estimation.
- Package format: package estimation.
- Power consumption profile: power estimation.
- Target cost: cost estimation.
There is also a testing procedure, which is continuously added during the design process.
(2) Design Specification Evaluation
This evaluates the feasibility of the design specification to determine whether it is practical.
(3) Device and Tool Selection
Choose the chip and the corresponding EDA tools, such as Xilinx chips with Vivado, Altera (Intel) chips with Quartus, or other product families.
(4) Design Phase
Adopt a top-down approach, working according to the structure of the chosen devices, using appropriate design methods to solve problems encountered during development.
(5) Verification
Simulate the design source code to ensure that the results of the RTL simulation are consistent with the gate-level simulation results. This is commonly referred to as pre-synthesis simulation. Timing analysis and post-synthesis simulation are also required before place-and-route.
(6) Final Evaluation
A formal review to confirm that there are no errors.
(7) System Integration and Testing
After chip fabrication, conduct continuous reliability testing of the device and the system.
2.2 Verilog HDL Design Approaches
(1) Bottom-Up
First, create a system block diagram, then partition it into modules, proceed with the design of each, and finally integrate them into a complete system.
Advantages: Individual sub-modules can be implemented relatively quickly.
Disadvantages: The overall system functionality may not be well controlled initially, the total integration time can be long, it demands strong collaboration among designers, and structural design errors can lead to significant losses.
(2) Top-Down
Perform a system-level design and high-level functional partitioning, then implement high-level functions using lower-level building blocks. The design is structured as a tree. It is possible to purchase end-node designs.
Advantages: System analysis is completed from the very start. The main simulation and debugging tasks are performed at a higher level, which helps discover structural design errors early. It facilitates system-level partitioning and project management.
Disadvantages: The smallest resulting units may be non-standard, potentially increasing production costs.
(3) Combined Approach
- At the start of the design, simulate the system behavior. Once successful, convert it into an RTL description.
- The RTL description: this level is hardware-relevant.
- Logic synthesis: convert the RTL description into a netlist.
3. Fundamental Concepts of Verilog Syntax
3.1 Modules
Verilog modules can correspond to different levels of abstraction:
(1) System level
(2) Algorithm level
(3) RTL level
(4) Gate level
(5) Switch level
Levels (1), (2), and (3) are behavioral. Front-end designers should master level (4), while back-end designers need level (5). Understanding the abstraction level of each module is crucial during the learning process.
3.2 Features
(1) Sequential execution (begin-end) or parallel execution (fork-join).
(2) Delay expressions (#) or event expressions.
(3) Triggering other events via named events.
(4) Conditional program structures (if, case) and looping constructs.
(5) Task structures offering parameterizable, time-consuming operations with no return value.
(6) Function structures that allow defining custom operators.
(7) Operators for building expressions (arithmetic, logical, bitwise).
(8) The language is also structural, usable at the gate and switch levels.
3.3 Module Instantiation
Other modules can be instantiated by their name, but attention must be paid to port consistency.
3.4 Module Testing
The syntax allowed for module testing is more permissive than that for synthesizable code, allowing the use of various test system functions (e.g., stop, display). The testing method essentially involves applying test signals to an instantiation of the module under test.
4. Module Structure
4.1 The Structure of a Module
A Verilog program consists of four parts:
Port definition, IO declaration, internal signal declaration, and functional definition.
module shift_unit (sig_a, sig_b, sig_c);
input sig_a;
output sig_b, sig_c;
// ...
endmodule
4.2 Data Types, Constants, and Variables
reg, wire, integer, parameter
reg: Register type, intended for assignments inside analwaysblock.wire: Net type, used as the assigned variable inassignstatements.integer: Integer type, used for loop indices and other general-purpose descriptions.parameter: Parameter, used for module-level constants.
Examples:
(1) Integer representations
1'b1, 2'o1, 3'd1, 4'h1,
'b1, 'h2, 'd3,
1, 2, 3,
x, z,
(2) Strings
"status", "line\n", "path\\",
"%info\%%"
(3) Variables
wire,trireg,integer- Memory (an array of
reg)
wire raw_data;
reg [7:0] filtered_data;
reg [7:0] memory_block [255:0];
5. Verilog HDL Operators
Fundamentals:
wireandregare treated as unsigned numbers.integerand real types are signed numbers.- If any operand is
x, the result isx.
// Arithmetic operations
logic [3:0] val_a, val_b, val_c;
val_a = 4'b1100; /* 12 */
val_b = 4'b0011; /* 3 */
val_c = 4'b1011; /* 11 */
$display(val_a * val_b); // result 4 (10_0100, truncated to 4 bits)
$display(val_a / val_b); // 4
$display(val_a + val_b); // 15
$display(val_a + val_c); // 7 (1_0111 truncated to 4 bits)
$display(val_a - val_b); // 9
$display((val_a + 1'b1) % val_b); // 1
$display(-10 % 3); // -1
$display(11 % -3); // 2
// Bitwise operations
logic [3:0] num_a, num_b, num_c, num_un, num_ze;
num_a = 4'b1100;
num_b = 4'b0011;
num_c = 4'b0101;
num_un = 4'b1xx0;
num_ze = 4'b0;
$displayb(~num_a); // 0011
$displayb(num_a & num_c); // 0100
$displayb(num_a | num_b); // 1111
$displayb(num_b ^ num_c); // 0110
$displayb(num_a ~^ num_c); // 0110
$displayb(num_un & num_ze); // 0000
// Logical operations
a = 2; b = 0; c = 4'hx;
$display(a && b); // 0
$display(a || b); // 1
$display(!a); // 0
$display(a || c); // 1
$display(a && c); // x
$display(!c); // x
$display(b && c); // 0
// Comparison operations
$display(a < b); // 1 (when a=5, b=10)
$display(a > b); // 0
$display(a >= c); // 1
$display(unk <= a); // x (where unk is 4'hx)
$display(4'b0 <= 4'hx); // x
Note: When printing with $display, the display of the sign bit depends on the context. Purely reg variables show the sign bit; purely constant values do not. Mixed contexts produce unknown behavior (may appear garbled in some simulators).
// Shift operations
logic [3:0] base_vec;
base_vec = 4'b1010;
$displayb(base_vec << 1); // 4'b0100
$displayb(base_vec >> 2); // 4'b0010
$displayb(4'bx << 2); // 4'bxx00
$displayb(4'b1101 << 2); // 4'b0100
// Concatenation operations
a = 1'b1;
b = 2'b00;
c = 6'b101001;
$displayb({a, b}); // 3'b100
$displayb({c[5:3], a}); // 4'b1011
$displayb({4{a}}); // 4'b1111
// Reduction operations
logic [3:0] vec_f, vec_g, vec_h;
vec_f = 4'b1111;
vec_g = 4'b0101;
vec_h = 4'b0x1z;
$displayb(&vec_f); // 1
$displayb(|vec_g); // 1
$displayb(^vec_g); // 0
$displayb(&vec_h); // 0
$displayb(|vec_h); // 1
$displayb(^vec_h); // x
// Conditional operator
$display(op == MODE_PLUS ? val_a + val_b : val_a - val_b);
Operator precedence generally follows the rules of the C language.
6. Verilog Statements
6.1 Block Statements
Sequential blocks (begin-end) and parallel blocks (fork-join). The key difference is the execution method. A sequential block executes statements one by one, while a parallel block executes them concurrently. The begin-end block is more commonly used as it aligns with C-like design habits. The main difference becomes apparent when handling delays.
6.2 Assignment Statements
=: blocking assignment. The right-hand side is fully evaluated, and the result is assigned to the left-hand side immediately, before moving to the next statement.<=: non-blocking assignment. The right-hand side is evaluated, and assignment to the left-hand side is scheduled. Execution then proceeds to the subsequent statement before the assignment takes effect.
Regarding timing:
For a parallel block (fork-join), the end time is determined by the longest delay within it.
For a sequential block (begin-end), the end time is the sum of all individual delays.
6.3 Conditional Statements
if-else and case statements, which are broadly similar to their C counterparts. The case statement has a specific syntax:
case (state_value)
16'd0: result_val = 7'b0111111;
16'd1: result_val = 7'b1011111;
16'd2: result_val = 7'b1101111;
16'd3: result_val = 7'b1110111;
16'd4: result_val = 7'b1111011;
16'd5: result_val = 7'b1111101;
16'd6: result_val = 7'b1111110;
default: result_val = 7'bx;
endcase
casez treats z as a don’t-care during comparison, and casex treats both x and z as don’t-cares. These can be used flexibly.
6.4 Loop Statements
forever, repeat, while, for
These four loop constructs cannot be synthesized directly and cannot exist independently in a synthesizable context.
forever begin endrepeat (iter_count) begin endwhile (check_cond) begin endfor (initial_step; exit_condition; iteration_step) begin end
6.5 Structural Specification Statements
initial, always, task, function
initial: executes only once.always: executes repeatedly.task: a reusable code block that can have parameters and return results via arguments.function: declared with a keyword, returns a value. A function cannot invoke a task.
task passes results through arguments, while function returns a result via its return value. As a simple analogy, a task is a quickly callable code segment, and a function defines a custom operator.
6.6 System Functions
$displayand$write: standard output tasks.$monitor: simulation monitoring task.$finishand$stop: simulation termination tasks.$timeand$realtime: time functions.$fopen, ..., and$readmemh: file and memory handling.$random: random number generator function.
6.7 Compiler Directives
`define: macro definition.`include: file inclusion.`ifdef...`else...`endif: conditional compilation.`timescale: time scale specification.`uselib: working library definition.