# 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 ```