---
# System prepended metadata

title: 'Verilog Tutorial 1: Gate Level Combinational'
tags: [ZYNQ]

---

# Verilog 1: Gate Level Combinational

Verilog is a hardware description language (HDL) used to model electronic systems. It is most commonly used in the design and verification of digital circuits.

This is an example of a Verilog module that connects an input switch to an output LED.
![verilog_digilent](https://hackmd.io/_uploads/HJL1m48bWg.png)
The structure and syntax used by Verilog are quite similar to those in C and it is a case-sensitive language.

In programming languages, there is no concept of time, but HDL can model propagation delays, clock periods, and timing checks.

### 1. Basic Lexical

An identifier gives a unique name to an object. It is composed of letters, digits, the underscore character (_), and the dollar sign ($). $ is usually used with a system task or function. The first character of an identifier must be a letter or underscore. Verilog is a case-sensitive language.

A comment is just for documentation purposes and will be ignored by software. Verilog has two forms of comments. A one-line comment starts with //, as in

```verilog
// This is a comment
```

A multiple-line comment is encapsulated between /* and */, as in

```verilog
/* This is comment line 1
   This is comment line 2
   This is comment line 3 */
```

### 2. Four-Value System

There are four basic values used in most data types:

- 0: for "logic 0", or a false condition
- 1: for "logic 1", or a true condition
- z: for the high-impedance state
- x: for an unknown value

The z value corresponds to the output of a tri-state buffer. The x value is usually used in modeling and simulation, representing a value that is not 0, 1, or z, such as an uninitialized input or output conflict.

### 3. Data Type Groups

Verilog has two main groups of data types: net and variable.

In the net group, the data types represent the physical connections between hardware components. The most commonly used data type in this group is wire. As the name indicates, it represents a connecting wire.

There are several examples of wire declarations.

```verilog
wire dO, dl;             // Two 1-bit signals
wire [7:0] data0, data1; // Two 8-bit data
wire [31:0] addr;        // 32-bit address
```

In the variable group, the data types represent abstract storage in behavioral modeling There are five data types in this group: reg, integer, real, time, and realtime. The most commonly used data type in this group is reg.

The simple difference between wire and reg is that wire is used only in a combinational circuit, while reg can be used either in a combinational or sequential circuit. wire cannot store a value, while reg can store some value.

### 4. Number Representation

An integer constant in Verilog can be represented in various formats. Its general form is

```
[sign][size]'[base][value]
```

The [size] term specifies the number of bits in a number. The [base] term specifies the base of the number, which can be the following:

- b or B: binary
- o or O: octal
- d or D: decimal
- h or H: hexadecimal

![number_representation](https://hackmd.io/_uploads/SJRLzBLWWl.png)

### 5. Program Skeleton

When we develop or examine a Verilog code, it is much easier to comprehend if we think in terms of "drawing a circuit" rather than "sequential algorithm."

The skeleton consists of three portions: I/O port declaration, signal declaration, and module body.

#### 5.1. Port Declaration
Let's consider this example code of a half-adder circuit.

```verilog=
module half_adder // Port declaration
    (
        input wire  a,
        input wire  b,
        output wire sum,
        output wire carry    
    );
    
    // Module body
    assign sum = a ^ b; // Continuous assignment
    assign carry = a & b;
    
endmodule
```

The port declaration of the previous code follows the following syntax:

```
module [module_name]
    (
        [mode] [data_type] [port_name],
        [mode] [data_type] [port_name],
        ...
        [mode] [data_type] [port_name]
    );
```

The [mode] term can be input, output, or inout, which represent the input, output, or bidirectional port, respectively. Note that there is no comma in the last declaration. The [data_type] term can be omitted if it is wire.

#### 5.2. Module Body

Unlike a program in the C language, in which the statements are executed sequentially, the module body of a synthesizable Verilog module can be thought of as a collection of circuit parts. These parts are operated in parallel and executed concurrently. There are several ways to describe a part: 

- Continuous assignment
- Procedural assignment or "always block"
- Module instantiation (structural)

In the previous code, we use continuous assignment to describe the module body, which follows the following syntax:

```
assign [signal_name] = [expression];
```

Each continuous assignment can be thought as a circuit part.

#### 5.3. Signal Declaration

Let's consider this example code of a full-adder circuit.

```verilog=
module full_adder
    (
        input wire  a,
        input wire  b,
        input wire  c,
        output wire sum,
        output wire carry 
    );
    
    // Signal declaration
    wire sum_0, carry_0, carry_1;
    
    // Module body
    half_adder half_adder_0 // Module instantiation
    (
        .a(a),
        .b(b),
        .sum(sum_0),
        .carry(carry_0)
    );
    half_adder half_adder_1
    (
        .a(sum_0),
        .b(c),
        .sum(sum),
        .carry(carry_1)
    );
    assign carry = carry_0 | carry_1; // Continuous assignment

endmodule
```

The full-adder code shows an example of a signal declaration, which follows the following syntax:

```
[data_type] [port_name];
```

A digital system is frequently composed of several smaller subsystems. This allows us to build a large system from simpler or predesigned components. Verilog provides a mechanism, known as module instantiation, to perform this task. This type of code is called structural description.

### 6. Testbench

After code is developed, it can be simulated in a host computer to verify the correctness of the circuit operation and can be synthesized to a physical device. Simulation is usually performed within the same HDL framework. We create a special program, known as a testbench, to mimic a physical lab bench.

```verilog=
`timescale 1ns / 1ps

module full_adder_tb();
    localparam T = 10;
    
    reg a;
    reg b;
    reg c;
    wire sum;
    wire carry;
    
    full_adder full_adder_0
    (
        .a(a),
        .b(b),
        .c(c),
        .sum(sum),
        .carry(carry)
    );
    
    initial
    begin
        a = 0; b = 0; c = 0; #T;
        a = 0; b = 0; c = 1; #T;
        a = 0; b = 1; c = 0; #T;
        a = 0; b = 1; c = 1; #T;
        a = 1; b = 0; c = 0; #T;
        a = 1; b = 0; c = 1; #T;
        a = 1; b = 1; c = 0; #T;
        a = 1; b = 1; c = 1; #T;                
    end
    
endmodule
```