0% found this document useful (0 votes)
20 views

Verilog Book

Uploaded by

shaik shareef
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views

Verilog Book

Uploaded by

shaik shareef
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 287

9

Introduction to Verilog
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2. Lexical Tokens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
White Space, Comments, Numbers, Identifiers, Operators, Verilog Keywords
3. Gate-Level Modelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Basic Gates, buf, not Gates, Three-State Gates; bufif1, bufif0, notif1, notif0
4. Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Value Set, Wire, Reg, Input, Output, Inout
Integer, Supply0, Supply1
Time, Parameter
5. Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Arithmetic Operators, Relational Operators, Bit-wise Operators, Logical Operators
Reduction Operators, Shift Operators, Concatenation Operator,
Conditional Operator: “?” Operator Precedence
6. Operands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Literals, Wires, Regs, and Parameters, Bit-Selects “x[3]” and Part-Selects “x[5:3]”
Function Calls
7. Modules. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Module Declaration, Continuous Assignment, Module Instantiations,
Parameterized Modules
8. Behavioral Modeling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Procedural Assignments, Delay in Assignment, Blocking and Nonblocking Assignments
begin ... end, for Loops, while Loops, forever Loops, repeat,
disable, if ... else if ... else
case, casex, casez
9. Timing Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Delay Control, Event Control, @, Wait Statement, Intra-Assignment Delay
10. Procedures: Always and Initial Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Always Block, Initial Block
11. Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Function Declaration, Function Return Value, Function Call, Function Rules, Example
12. Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
13. Component Inference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Registers, Flip-flops, Counters, Multiplexers, Adders/Subtracters, Tri-State Buffers
Other Component Inferences
14. Finite State Machines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Counters, Shift Registers
15. Compiler Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Time Scale, Macro Definitions, Include Directive
16. System Tasks and Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
$display, $strobe, $monitor $time, $stime, $realtime,
$reset, $stop, $finish $deposit, $scope, $showscope, $list
17. Test Benches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Synchronous Test Bench

Introduction to Verilog Friday, January 05, 2001 9:34 pm Peter M. Nyasulu


Introduction to Verilog

1. Introduction
Verilog HDL is one of the two most common Hardware Description Languages (HDL) used by integrated circuit
(IC) designers. The other one is VHDL.
HDL’s allows the design to be simulated earlier in the design cycle in order to correct errors or experiment with
different architectures. Designs described in HDL are technology-independent, easy to design and debug, and are
usually more readable than schematics, particularly for large circuits.

Verilog can be used to describe designs at four levels of abstraction:


(i) Algorithmic level (much like c code with if, case and loop statements).
(ii) Register transfer level (RTL uses registers connected by Boolean equations).
(iii) Gate level (interconnected AND, NOR etc.).
(iv) Switch level (the switches are MOS transistors inside gates).
The language also defines constructs that can be used to control the input and output of simulation.

More recently Verilog is used as an input for synthesis programs which will generate a gate-level description (a
netlist) for the circuit. Some Verilog constructs are not synthesizable. Also the way the code is written will greatly
effect the size and speed of the synthesized circuit. Most readers will want to synthesize their circuits, so nonsynthe-
sizable constructs should be used only for test benches. These are program modules used to generate I/O needed to
simulate the rest of the design. The words “not synthesizable” will be used for examples and constructs as needed that
do not synthesize.

There are two types of code in most HDLs:


Structural, which is a verbal wiring diagram without storage.
assign a=b & c | d; /* “|” is a OR */
assign d = e & (~c);
Here the order of the statements does not matter. Changing e will change a.
Procedural which is used for circuits with storage, or as a convenient way to write conditional logic.
always @(posedge clk) // Execute the next statement on every rising clock edge.
count <= count+1;
Procedural code is written like c code and assumes every assignment is stored in memory until over written. For syn-
thesis, with flip-flop storage, this type of thinking generates too much storage. However people prefer procedural
code because it is usually much easier to write, for example, if and case statements are only allowed in procedural
code. As a result, the synthesizers have been constructed which can recognize certain styles of procedural code as
actually combinational. They generate a flip-flop only for left-hand variables which truly need to be stored. However
if you stray from this style, beware. Your synthesis will start to fill with superfluous latches.

This manual introduces the basic and most common Verilog behavioral and gate-level modelling constructs, as
well as Verilog compiler directives and system functions. Full description of the language can be found in Cadence
Verilog-XL Reference Manual and Synopsys HDL Compiler for Verilog Reference Manual. The latter emphasizes
only those Verilog constructs that are supported for synthesis by the Synopsys Design Compiler synthesis tool.

In all examples, Verilog keyword are shown in boldface. Comments are shown in italics.

Friday, January 05, 2001 9:34 pm 1 Peter M. Nyasulu


Introduction to Verilog

2. Lexical Tokens
Verilog source text files consists of the following lexical tokens:

2.1. White Space


White spaces separate words and can contain spaces, tabs, new-lines and form feeds. Thus a statement can extend
over multiple lines without special continuation characters.

2.2. Comments
Comments can be specified in two ways (exactly the same way as in C/C++):
- Begin the comment with double slashes (//). All text between these characters and the end of the line will be
ignored by the Verilog compiler.
- Enclose comments between the characters /* and */. Using this method allows you to continue comments on
more than one line. This is good for “commenting out” many lines code, or for very brief in-line comments.

Example 2 .1
a = c + d; // this is a simple comment
/* however, this comment continues on more
than one line */
assign y = temp_reg;
assign x=ABC /* plus its compliment*/ + ABC_

2.3. Numbers
Number storage is defined as a number of bits, but values can be specified in binary, octal, decimal or hexadecimal
(See Sect. 6.1. for details on number notation).
Examples are 3’b001, a 3-bit number, 5’d30, (=5’b11110), and 16‘h5ED4, (=16’d24276)

2.4. Identifiers
Identifiers are user-defined words for variables, function names, module names, block names and instance names.
Identifiers begin with a letter or underscore (Not with a number or $) and can include any number of letters, digits and
underscores. Identifiers in Verilog are case-sensitive.

Syntax Example 2 .2
allowed symbols adder // use underscores to make your
ABCDE . . . abcdef. . . 1234567890 _$ by_8_shifter // identifiers more meaningful
not allowed: anything else especially _ABC_ /* is not the same as */ _abc_
- &#@ Read_ // is often used for NOT Read

2.5. Operators
Operators are one, two and sometimes three characters used to perform operations on variables.
Examples include >, +, ~, &, !=. Operators are described in detail in “Operators” on p. 6.

2.6. Verilog Keywords


These are words that have special meaning in Verilog. Some examples are assign, case, while, wire, reg, and, or,
nand, and module. They should not be used as identifiers. Refer to Cadence Verilog-XL Reference Manual for a
complete listing of Verilog keywords. A number of them will be introduced in this manual. Verilog keywords also
includes Compiler Directives (Sect. 15. ) and System Tasks and Functions (Sect. 16. ).

Friday, January 05, 2001 9:34 pm 2 Peter M. Nyasulu


Introduction to Verilog

3. Gate-Level Modelling
Primitive logic gates are part of the Verilog language. Two properties can be specified, drive_strength and delay.
Drive_strength specifies the strength at the gate outputs. The strongest output is a direct connection to a source, next
comes a connection through a conducting transistor, then a resistive pull-up/down. The drive strength is usually not
specified, in which case the strengths defaults to strong1 and strong0. Refer to Cadence Verilog-XL Reference Man-
ual for more details on strengths.
Delays: If no delay is specified, then the gate has no propagation delay; if two delays are specified, the first represent
the rise delay, the second the fall delay; if only one delay is specified, then rise and fall are equal. Delays are ignored
in synthesis. This method of specifying delay is a special case of “Parameterized Modules” on page 11. The parame-
ters for the primitive gates have been predefined as delays.

3.1. Basic Gates


These implement the basic logic gates. They have one output and one or more inputs. In the gate instantiation syntax
shown below, GATE stands for one of the keywords and, nand, or, nor, xor, xnor.

Syntax Example 3 .1
GATE (drive_strength) # (delays)
instance_name1(output, input_1, and c1 (o, a, b, c, d); // 4-input AND called c1 and
input_2,..., input_N), c2 (p, f g); // a 2-input AND called c2.
instance_name2(outp,in1, in2,..., inN); or #(4, 3) ig (o, a, b); /* or gate called ig (instance name);
Delays is rise time = 4, fall time = 3 */
#(rise, fall) or xor #(5) xor1 (a, b, c); // a = b XOR c after 5 time units
# rise_and_fall or xor (pull1, strong0) #5 (a,b,c); /* Identical gate with pull-up
#(rise_and_fall) strength pull1 and pull-down strength strong0. */

3.2. buf, not Gates


These implement buffers and inverters, respectively. They have one input and one or more outputs. In the gate instan-
tiation syntax shown below, GATE stands for either the keyword buf or not

Syntax Example 3 .2
not #(5) not_1 (a, c); // a = NOT c after 5 time units
GATE (drive_strength) # (delays)
buf c1 (o, p, q, r, in); // 5-output and 2-output buffers
instance_name1(output_1, output_2,
c2 (p, f g);
..., output_n, input),
instance_name2(out1, out2, ..., outN, in);

3.3. Three-State Gates; bufif1, bufif0, notif1, notif0


These implement 3-state buffers and inverters. They propagate z (3-state or high-impedance) if their control signal is
deasserted. These can have three delay specifications: a rise time, a fall time, and a time to go into 3-state.
bufif0 notif0 Example 3 .3
A BUS = Z
bufif0 #(5) not_1 (BUS, A, CTRL); /* BUS = A
En En
CTRL=1
5 time units after CTRL goes low. */
notif1 #(3,4,6) c1 (bus, a, b, cntr); /* bus goes tri-state
bufif1 notif1 6 time units after ctrl goes low. */
En En

Friday, January 05, 2001 9:34 pm 3 Peter M. Nyasulu


Introduction to Verilog

4. Data Types
4.1. Value Set
Verilog consists of only four basic values. Almost all Verilog data types store all these values:
0 (logic zero, or false condition)
1 (logic one, or true condition)
x (unknown logic value) x and z have limited use for synthesis.
z (high impedance state)

4.2. Wire
A wire represents a physical wire in a circuit and is used to connect gates or modules. The value of a wire can be
read, but not assigned to, in a function or block. See “Functions” on p. 19, and “Procedures: Always and Initial
Blocks” on p. 18. A wire does not store its value but must be driven by a continuous assignment statement or by con-
necting it to the output of a gate or module. Other specific types of wires include:
wand (wired-AND);:the value of a wand depend on logical AND of all the drivers connected to it.
wor (wired-OR);: the value of a wor depend on logical OR of all the drivers connected to it.
tri (three-state;): all drivers connected to a tri must be z, except one (which determines the value of the tri).

Syntax Example 4 .1
wire c // simple wire
wire [msb:lsb] wire_variable_list;
wand d;
wand [msb:lsb] wand_variable_list;
assign d = a; // value of d is the logical AND of
wor [msb:lsb] wor_variable_list;
assign d = b; // a and b
tri [msb:lsb] tri_variable_list;
wire [9:0] A; // a cable (vector) of 10 wires.

4.3. Reg
A reg (register) is a data object that holds its value from one procedural assignment to the next. They are used only in
functions and procedural blocks. See “Wire” on p. 4 above. A reg is a Verilog variable type and does not necessarily
imply a physical register. In multi-bit registers, data is stored as unsigned numbers and no sign extension is done for
what the user might have thought were two’s complement numbers.

Syntax Example 4 .2
reg a; // single 1-bit register variable
reg [msb:lsb] reg_variable_list;
reg [7:0] tom; // an 8-bit vector; a bank of 8 registers.
reg [5:0] b, c; // two 6-bit variables

4.4. Input, Output, Inout


These keywords declare input, output and bidirectional ports of a module or task. Input and inout ports are of type
wire. An output port can be configured to be of type wire, reg, wand, wor or tri. The default is wire.

Syntax Example 4 .3
module sample(b, e, c, a); //See “Module Instantiations” on p. 10
input [msb:lsb] input_port_list; input a; // An input which defaults to wire.
output [msb:lsb] output_port_list; output b, e; // Two outputs which default to wire
inout [msb:lsb] inout_port_list; output [1:0] c; /* A two-it output. One must declare its
type in a separate statement. */
reg [1:0] c; // The above c port is declared as reg.

Friday, January 05, 2001 9:34 pm 4 Peter M. Nyasulu


Introduction to Verilog

4.5. Integer
Integers are general-purpose variables. For synthesois they are used mainly loops-indicies, parameters, and con-
stants. See“Parameter” on p. 5. They are of implicitly of type reg. However they store data as signed numbers
whereas explicitly declared reg types store them as unsigned. If they hold numbers which are not defined at compile
time, their size will default to 32-bits. If they hold constants, the synthesizer adjusts them to the minimum width
needed at compilation.

Syntax Example 4 .4
integer a; // single 32-bit integer
integer integer_variable_list;
assign b=63; // 63 defaults to a 7-bit variable.
... integer_constant ... ;

4.6. Supply0, Supply1


Supply0 and supply1 define wires tied to logic 0 (ground) and logic 1 (power), respectively.

Syntax Example 4 .5

supply0 logic_0_wires; supply0 my_gnd; // equivalent to a wire assigned 0


supply1 logic_1_wires; supply1 a, b;

4.7. Time
Time is a 64-bit quantity that can be used in conjunction with the $time system task to hold simulation time. Time is
not supported for synthesis and hence is used only for simulation purposes.

Syntax Example 4 .6

time time_variable_list; time c;


c = $time; // c = current simulation time

4.8. Parameter
A parameter defines a constant that can be set when you instantiate a module. This allows customization of a mod-
ule during instantiation. See also “Parameterized Modules” on page 11.

Syntax Example 4 .7
parameter add = 2’b00, sub = 3’b111;
parameter par_1 = value,
parameter n = 4;
par_2 = value, .....;
parameter n = 4;
parameter [range] parm_3 = value
parameter [3:0] param2 = 4’b1010;
...
reg [n-1:0] harry; /* A 4-bit register whose length is
set by parameter n above. */
always @(x)
y = {{(add - sub){x}}; // The replication operator Sect. 5.8.
if (x) begin
state = param2[1]; else state = param2[2];
end

Friday, January 05, 2001 9:34 pm 5 Peter M. Nyasulu


Introduction to Verilog

5. Operators
5.1. Arithmetic Operators
These perform arithmetic operations. The + and - can be used as either unary (-z) or binary (x-y) operators.

Operators Example 5 .1
parameter n = 4;
+ (addition)
reg[3:0] a, c, f, g, count;
- (subtraction)
f = a + c;
* (multiplication)
g = c - n;
/ (division)
count = (count +1)%16; //Can count 0 thru 15.
% (modulus)

5.2. Relational Operators


Relational operators compare two operands and return a single bit 1or 0. These operators synthesize into comparators.
Wire and reg variables are positive Thus (-3’b001) = = 3’b111 and (-3d001)>3d110. However for integers -1< 6.

Operators Example 5 .2 Equivalent Statement


if (x = = y) e = 1;
< (less than) else e = 0; e = (x == y);
<= (less than or equal to)
> (greater than) // Compare in 2’s compliment; a>b
>= (greater than or equal to) reg [3:0] a,b;
== (equal to) if (a[3]= = b[3]) a[2:0] > b[2:0];
!= (not equal to) else b[3];

5.3. Bit-wise Operators


Bit-wise operators do a bit-by-bit comparison between two operands. However see“Reduction Operators” on p. 7.

Operators Example 5 .3
a a(0
~ (bitwise NOT) module and2 (a, b, c); b(0) c(0
2
& (bitwise AND) input [1:0] a, b;
| (bitwise OR) output [1:0] c; a(1)
^ (bitwise XOR) assign c = a & b; b b(1) c(1)
~^ or ^~(bitwise XNOR) endmodule 2

5.4. Logical Operators


Logical operators return a single bit 1 or 0. They are the same as bit-wise operators only for single bit operands. They
can work on expressions, integers or groups of bits, and treat all values that are nonzero as “1”. Logical operators are
typically used in conditional (if ... else) statements since they work with expressions.
Operators Example 5 .4
wire[7:0] x, y, z; // x, y and z are multibit variables.
! (logical NOT) reg a;
&& (logical AND) ...
|| (logical OR) if ((x == y) && (z)) a = 1; // a = 1 if x equals y, and z is nonzero.
else a = !x; // a =0 if x is anything but zero.

Friday, January 05, 2001 9:34 pm 6 Peter M. Nyasulu


Introduction to Verilog

5.5. Reduction Operators


Reduction operators operate on all the bits of an operand vector and return a single-bit value. These are the unary (one
argument) form of the bit-wise operators above.

Operators Example 5 .5
module chk_zero (a, z); a(0)
& (reduction AND) a a(1) z
input [2:0] a;
| (reduction OR) a(2)
output z; 3
~& (reduction NAND)
assign z = ~| a; // Reduction NOR
~| (reduction NOR)
endmodule
^ (reduction XOR)
~^ or ^~(reduction XNOR)

5.6. Shift Operators


Shift operators shift the first operand by the number of bits specified by the second operand. Vacated positions are
filled with zeros for both left and right shifts (There is no sign extension).

Operators Example 5 .6
assign c = a << 2; /* c = a shifted left 2 bits;
<< (shift left)
vacant positions are filled with 0’s */
>> (shift right)

5.7. Concatenation Operator


The concatenation operator combines two or more operands to form a larger vector.

Operators Example 5 .7
wire [1:0] a, b; wire [2:0] x; wire [3;0] y, Z;
{ } (concatenation) assign x = {1’b0, a}; // x[2]=0, x[1]=a[1], x[0]=a[0]
assign y = {a, b}; /* y[3]=a[1], y[2]=a[0], y[1]=b[1],
y[0]=b[0] */

assign {cout, y} = x + Z; // Concatenation of a result

5.8. Replication Operator


The replication operator makes multiple copies of an item.

Operators Example 5 .8
wire [1:0] a, b; wire [4:0] x;
{n{item}} (n fold replication of an item) assign x = {2{1’b0}, a}; // Equivalent to x = {0,0,a }
assign y = {2{a}, 3{b}}; //Equivalent to y = {a,a,b,b}

For synthesis, Synopsis did not like a zero replication. For example:-
parameter n=5, m=5;
assign x= {(n-m){a}}

Friday, January 05, 2001 9:34 pm 7 Peter M. Nyasulu


Introduction to Verilog

5.9. Conditional Operator: “?”


Conditional operator is like those in C/C++. They evaluate one of the two expressions based on a condition. It will
synthesize to a multiplexer (MUX).

Operators Example 5 .9
x y
assign a = (g) ? x : y; g
(cond) ? (result if cond true): assign a = (inc = = 2) ? a+1 : a-1;
1 1
(result if cond false) /* if (inc), a = a+1, else a = a-1 */

5.10. Operator Precedence


Table 6.1 shows the precedence of operators from highest to lowest. Operators on the same level evaluate from left to
right. It is strongly recommended to use parentheses to define order of precedence and improve the readability of
your code.

Operator Name
[ ] bit-select or part-select
( ) parenthesis
!, ~ logical and bit-wise NOT
&, |, ~&, ~|, ^, ~^, ^~ reduction AND, OR, NAND, NOR, XOR, XNOR;
If X=3’B101 and Y=3’B110, then X&Y=3’B100, X^Y=3’B011;
+, - unary (sign) plus, minus; +17, -7
{ } concatenation; {3’B101, 3’B110} = 6’B101110;
{{ }} replication; {3{3'B110}} = 9'B110110110
*, /, % multiply, divide, modulus; / and % not be supported for synthesis
+, - binary add, subtract.
<<, >> shift left, shift right; X<<2 is multiply by 4
<, <=, >, >= comparisons. Reg and wire variables are taken as positive numbers.
= =, != logical equality, logical inequality
= = =, != = case equality, case inequality; not synthesizable
& bit-wise AND; AND together all the bits in a word
^, ~^, ^~ bit-wise XOR, bit-wise XNOR
| bit-wise OR; AND together all the bits in a word
&&, logical AND. Treat all variables as False (zero) or True (nonzero).
logical OR. (7||0) is (T||F) = 1, (2||-3) is (T||T) =1,
||
(3&&0) is (T&&F) = 0.
?: conditional. x=(cond)? T : F;
Table 5.1: Verilog Operators Precedence

Friday, January 05, 2001 9:34 pm 8 Peter M. Nyasulu


Introduction to Verilog

6. Operands
6.1. Literals
Literals are constant-valued operands that can be used in Verilog expressions. The two common Verilog literals are:
(a) String: A string literal is a one-dimensional array of characters enclosed in double quotes (“ “).
(b) Numeric: constant numbers specified in binary, octal, decimal or hexadecimal.

Number Syntax Example 6 .1

n’Fddd..., where “time is”// string literal


n - integer representing number of bits 267 // 32-bit decimal number
F - one of four possible base formats: 2’b01 // 2-bit binary
b (binary), o (octal), d (decimal), 20’hB36F// 20-bit hexadecimal number
h (hexadecimal). Default is d. ‘o62 // 32-bit octal number
dddd - legal digits for the base format

6.2. Wires, Regs, and Parameters


Wires, regs and parameters can also be used as operands in Verilog expressions. These data objects are described in
more detail in Sect. 4. .

6.3. Bit-Selects “x[3]” and Part-Selects “x[5:3]”


Bit-selects and part-selects are a selection of a single bit and a group of bits, respectively, from a wire, reg or parame-
ter vector using square brackets “[ ]”. Bit-selects and part-selects can be used as operands in expressions in much the
same way that their parent data objects are used.

Syntax Example 6 .2
reg [7:0] a, b;
variable_name[index]
reg [3:0] ls;
variable_name[msb:lsb]
reg c;
c = a[7] & b[7]; // bit-selects
ls = a[7:4] + b[3:0]; // part-selects

6.4. Function Calls


The return value of a function can be used directly in an expression without first assigning it to a register or wire var-
iable. Simply place the function call as one of the operands. Make sure you know the bit width of the return value of
the function call. Construction of functions is described in “Functions” on page 19

Syntax Example 6 .3
assign a = b & c & chk_bc(c, b);// chk_bc is a function
function_name (argument_list)
. . ./* Definition of the function */
function chk_bc;// function definition
input c,b;
chk_bc = b^c;
endfunction

Friday, January 05, 2001 9:34 pm 9 Peter M. Nyasulu


Introduction to Verilog

7. Modules
7.1. Module Declaration
A module is the principal design entity in Verilog. The first line of a module declaration specifies the name and port
list (arguments). The next few lines specifies the i/o type (input, output or inout, see Sect. 4.4. ) and width of each
port. The default port width is 1 bit.
Then the port variables must be declared wire, wand,. . ., reg (See Sect. 4. ). The default is wire. Typically inputs are
wire since their data is latched outside the module. Outputs are type reg if their signals were stored inside an always
or initial block (See Sect. 10. ).

Syntax Example 7 .1 add

module module_name (port_list); module add_sub(add, in1, in2, oot); in1


input [msb:lsb] input_port_list; input add; // defaults to wire oot
8 add_sub
output [msb:lsb] output_port_list; input [7:0] in1, in2; wire in1, in2; in2
inout [msb:lsb] inout_port_list; 8
output [7:0] oot; reg oot;
... statements ... 8
... statements ...
endmodule endmodule

7.2. Continuous Assignment


The continuous assignment is used to assign a value onto a wire in a module. It is the normal assignment outside of
always or initial blocks (See Sect. 10. ). Continuous assignment is done with an explicit assign statement or by
assigning a value to a wire during its declaration. Note that continuous assignment statements are concurrent and are
continuously executed during simulation. The order of assign statements does not matter. Any change in any of the
right-hand-side inputs will immediately change a left-hand-side output.

Syntax Example 7 .2
wire [1:0] a = 2’b01; // assigned on declaration
wire wire_variable = value;
assign wire_variable = expression; assign b = c & d; // using assign statement
assign d = x | y; c b
/* The order of the assign statements x d
y
does not matter. */

7.3. Module Instantiations


Module declarations are templates from which one creates actual objects (instantiations). Modules are instantiated
inside other modules, and each instantiation creates a unique object from the template. The exception is the top-level
module which is its own instantiation.

The instantiated module’s ports must be matched to those defined in the template. This is specified:
(i) by name, using a dot(.) “ .template_port_name (name_of_wire_connected_to_port )”.
or(ii) by position, placing the ports in exactly the same positions in the port lists of both the template and the instance.

Friday, January 05, 2001 9:34 pm 10 Peter M. Nyasulu


Introduction to Verilog

Syntax for Instantiation Example 7 .3 // MODULE INSTANTIATIONS


module_name wire [3:0] in1, in2;
instance_name_1 (port_connection_list), // MODULE DEFINITION wire [3:0] o1, o2;
instance_name_2 (port_connection_list), /* C1 is an instance of module and4
...... module and4(a, b, c); C1 ports referenced by position */
instance_name_n (port_connection_list); input [3:0] a, b; and4 C1 (in1, in2, o1);
output [3:0] c; /* C2 is another instance of and4.
assign c = a & b; C2 ports are referenced to the
endmodule declaration by name. */
and4 C2 ( .c(o2), .a(in1), .b(in2));

Modules may not be instantiated inside procedural blocks. See “Procedures: Always and Initial Blocks” on page 18.

7.4. Parameterized Modules


You can build modules that are parameterized and specify the value of the parameter at each instantiation of the mod-
ule. See “Parameter” on page 5 for the use of parameters inside a module. Primitive gates have parameters which
have been predefined as delays. See “Basic Gates” on page 3.

Syntax Example 7 .4
// MODULE DEFINITION
module_name #(parameter_values) module shift_n (it, ot); // used in module test_shift.
instance_name(port_connection_list); input [7:0] it; output [7:0] ot;
parameter n = 2;‘ // default value of n is 2
assign ot = (it << n); // it shifted left n times
endmodule

// PARAMETERIZED INSTANTIATIONS
wire [7:0] in1, ot1, ot2, ot3;
shift_n shft2(in1, ot1), // shift by 2; default
shift_n #(3) shft3(in1, ot2); // shift by 3; override parameter 2.
shift_n #(5) shft5(in1, ot3); // shift by 5; override parameter 2.

Synthesis does not support the defparam keyword which is an alternate way of changing parameters.

Friday, January 05, 2001 9:34 pm 11 Peter M. Nyasulu


Introduction to Verilog

8. Behavioral Modeling
Verilog has four levels of modelling:
1) The switch level which includes MOS transistors modelled as switches. This is not discussed here.
2) The gate level. See “Gate-Level Modelling” on p. 3
3) The Data-Flow level. See Example 7 .4 on page 11
4) The Behavioral or procedural level described below.
Verilog procedural statements are used to model a design at a higher level of abstraction than the other levels. They
provide powerful ways of doing complex designs. However small changes n coding methods can cause large changes
in the hardware generated. Procedural statements can only be used in procedures. Verilog procedures are described
later in “Procedures: Always and Initial Blocks” on page 18,“Functions” on page 19, and “Tasks Not Synthesizable”
on page 21.

8.1. Procedural Assignments


Procedural assignments are assignment statements used within Verilog procedures (always and initial blocks). Only
reg variables and integers (and their bit/part-selects and concatenations) can be placed left of the “=” in procedures.
The right hand side of the assignment is an expression which may use any of the operator types described in Sect. 5.

8.2. Delay in Assignment (not for synthesis)


In a delayed assignment ∆t time units pass before the statement is executed and the left-hand assignment is made.
With intra-assignment delay, the right side is evaluated immediately but there is a delay of ∆t before the result is
place in the left hand assignment. If another procedure changes a right-hand side signal during ∆t, it does not effect
the output. Delays are not supported by synthesis tools.
Syntax for Procedural Assignment Example 8 .1
variable = expression
Delayed assignment reg [6:0] sum; reg h, ziltch;
#∆t variable = expression; sum[7] = b[7] ^ c[7]; // execute now.
Intra-assignment delay ziltch = #15 ckz&h; /* ckz&a evaluated now; ziltch changed
variable = #∆t expression; after 15 time units. */
#10 hat = b&c; /* 10 units after ziltch changes, b&c is
evaluated and hat changes. */

8.3. Blocking Assignments


Procedural (blocking) assignments (=) are done sequentially in the order the statements are written. A second
assignment is not started until the preceding one is complete. See also Sect. 9.4.
Syntax Example 8 .2. For simulation
Blocking initial
variable = expression; begin
variable = #∆t expression; a=1; b=2; c=3;
grab inputs now, deliver ans. #5 a = b + c; // wait for 5 units, and execute a= b + c =5.
later. d = a; // Time continues from last line, d=5 = b+c at t=5.
#∆t variable = expression;
grab inputs later, deliver ans. Example 0 .1. For synthesis X Y Z
later 1D 1D
always @( posedge clk)
C1 C1
begin
Z=Y; Y=X; // shift register
x y
y=x; z=y; //parallel ff. 1D 1D z
C1 C1

Friday, January 05, 2001 9:34 pm 12 Peter M. Nyasulu


Introduction to Verilog

8.4. Nonblocking (RTL) Assignments (see below for synthesis)


RTL (nonblocking) assignments (<=), which follow each other in the code, are done in parallel. The right hand
side of nonblocking assignments is evaluated starting from the completion of the last blocking assignment or if none,
the start of the procedure. The transfer to the left hand side is made according to the delays. A delay in a non-blocking
statement will not delay the start of any subsequent statement blocking or non-blocking.
A good habit is to use “<=” if the same variable appears on both sides of the equal sign (Example 0 .1 on page 13).
For synthesis
• One must not mix “<=” or “=” in the same procedure.
• “<=” best mimics what physical flip-flops do; use it for “always @ (posedge clk ..) type procedures.
• “=” best corresponds to what c/c++ code would do; use it for combinational procedures.
:
Syntax Example 0 .1. For simulation
Non-Blocking initial
variable <= expression; begin
variable <= #∆t expression; #3 b <= a; /* grab a at t=0 Deliver b at t=3.
#∆t variable <= expression; #6 x <= b + c; // grab b+c at t=0, wait and assign x at t=6.
x is unaffected by b’s change. */

Example 0 .2. For synthesis X Y Z


always @( posedge clk) 1D 1D
C1 C1
begin
Z<=Y; Y<=X; // shift register x y z
1D 1D
y<=x; z<=y; //also a shift register.
C1 C1

Example 8 .3. Use <= to transform a variable into itself.


reg G[7:0];
always @( posedge clk)
G <= { G[6:0], G[7]}; // End around rotate 8-bit register.

The following example shows interactions between blocking and non-blocking for simulation. Do not mix the two
types in one procedure for synthesis.
Syntax Example 8 .4 for simulation only
initial begin
Non-Blocking a=1; b=2; c=3; x=4;
variable <= expression; #5 a = b + c; // wait for 5 units, then grab b,c and execute a=2+3.
variable <= #∆t expression; d = a; // Time continues from last line, d=5 = b+c at t=5.
?#∆t variable <=expression; x <= #6 b + c;// grab b+c now at t=5, don’t stop, make x=5 at t=11.
Blocking b <= #2 a; /* grab a at t=5 (end of last blocking statement).
variable = expression; Deliver b=5 at t=7. previous x is unaffected by b change. */
variable = #∆t expression; y <= #1 b + c;// grab b+c at t=5, don’t stop, make x=5 at t=6.
#∆t variable = expression; #3 z = b + c; // grab b+c at t=8 (#5+#3), make z=5 at t=8.
w <= x // make w=4 at t=8. Starting at last blocking assignm.

8.5. begin ... end


begin ... end block statements are used to group several statements for use where one statement is syntactically
allowed. Such places include functions, always and initial blocks, if, case and for statements. Blocks can optionally
be named. See “disable” on page 15) and can include register, integer and parameter declarations.

Friday, January 05, 2001 9:34 pm 13 Peter M. Nyasulu


Introduction to Verilog

Syntax Example 8 .5

begin : block_name function trivial_one; // The block name is “trivial_one.”


reg [msb:lsb] reg_variable_list; input a;
integer [msb:lsb] integer_list; begin: adder_blk; // block named adder, with
parameter [msb:lsb] parameter_list; integer i; // local integer i
... statements ... ... statements ...
end end

8.6. for Loops


Similar to for loops in C/C++, they are used to repeatedly execute a statement or block of statements. If the loop con-
tains only one statement, the begin ... end statements may be omitted.

Syntax Example 8 .6

for (count = value1; for (j = 0; j <= 7; j = j + 1)


count </<=/>/>= value2; begin
count = count +/- step) c[j] = a[j] & b[j];
begin d[j] = a[j] | b[j];
... statements ... end
end

8.7. while Loops


The while loop repeatedly executes a statement or block of statements until the expression in the while statement
evaluates to false. To avoid combinational feedback during synthesis, a while loop must be broken with an
@(posedge/negedge clock) statement (Section 9.2). For simulation a delay inside the loop will suffice. If the loop
contains only one statement, the begin ... end statements may be omitted.

Syntax Example 8 .7

while (expression) while (!overflow) begin


begin @(posedge clk);
... statements ... a = a + 1;
end end

8.8. forever Loops


The forever statement executes an infinite loop of a statement or block of statements. To avoid combinational feed-
back during synthesis, a forever loop must be broken with an @(posedge/negedge clock) statement (Section 9.2). For
simulation a delay inside the loop will suffice. If the loop contains only one statement, the begin ... end statements
may be omitted. It is
Syntax Example 8 .8
forever begin
forever @(posedge clk); // or use a= #9 a+1;
begin a = a + 1;
... statements ... end
end

8.9. repeat Not synthesizable


The repeat statement executes a statement or block of statements a fixed number of times.

Friday, January 05, 2001 9:34 pm 14 Peter M. Nyasulu


Introduction to Verilog

Syntax Example 8 .9

repeat (number_of_times) repeat (2) begin // after 50, a = 00,


begin #50 a = 2’b00; // after 100, a = 01,
... statements ... #50 a = 2’b01; // after 150, a = 00,
end end// after 200, a = 01

8.10. disable
Execution of a disable statement terminates a block and passes control to the next statement after the block. It is like
the C break statement except it can terminate any loop, not just the one in which it appears.
Disable statements can only be used with named blocks.
Syntax Example 8 .10

disable block_name; begin: accumulate


forever
begin
@(posedge clk);
a = a + 1;
if (a == 2’b0111) disable accumulate;
end
end

8.11. if ... else if ... else


The if ... else if ... else statements execute a statement or block of statements depending on the result of the expression
following the if. If the conditional expressions in all the if’s evaluate to false, then the statements in the else block, if
present, are executed.
There can be as many else if statements as required, but only one if block and one else block. If there is one statement
in a block, then the begin .. end statements may be omitted.
Both the else if and else statements are optional. However if all possibilities are not specifically covered, synthesis
will generated extra latches.

Syntax Example 8 .11

if (expression) if (alu_func == 2’b00)


begin aluout = a + b;
... statements ... else if (alu_func == 2’b01)
end aluout = a - b;
else if (expression) else if (alu_func == 2’b10)
begin aluout = a & b;
... statements ... else // alu_func == 2’b11
end aluout = a | b;
... more else if blocks ...
else if (a == b) // This if with no else will generate
begin begin // a latch for x and ot. This is so they
... statements ... x = 1; // will hold there old value if (a != b).
end ot = 4’b1111;
end

Friday, January 05, 2001 9:34 pm 15 Peter M. Nyasulu


Introduction to Verilog

8.12. case
The case statement allows a multipath branch based on comparing the expression with a list of case choices.
Statements in the default block executes when none of the case choice comparisons are true (similar to the else block
in the if ... else if ... else). If no comparisons , including delault, are true, synthesizers will generate unwanted latches.
Good practice says to make a habit of puting in a default whether you need it or not.
If the defaults are dont cares, define them as ‘x’ and the logic minimizer will treat them as don’t cares.
Case choices may be a simple constant or expression, or a comma-separated list of same.

Syntax Example 0 .1
case (alu_ctr)
case (expression) 2’b00: aluout = a + b;
case_choice1: 2’b01: aluout = a - b;
begin 2’b10: aluout = a & b;
... statements ... default: aluout = 1’bx; // Treated as don’t cares for
end endcase // minimum logic generation.
case_choice2:
begin
... statements ... Example 0 .2
end case (x, y, z)
... more case choices blocks ... 2’b00: aluout = a + b; //case if x or y or z is 2’b00.
default: 2’b01: aluout = a - b;
begin 2’b10: aluout = a & b;
... statements ... default: aluout = a | b;
end endcase
endcase

8.13. casex
In casex(a) the case choices constant “a” may contain z, x or ? which are used as don’t cares for comparison. With
case the corresponding simulation variable would have to match a tri-state, unknown, or either signal. In short, case
uses x to compare with an unknown signal. Casex uses x as a don’t care which can be used to minimize logic.

Syntax Example 8 .12


casex (a)
same as for case statement 2’b1x: msb = 1; // msb = 1 if a = 10 or a = 11
(Section 8.10) // If this were case(a) then only a=1x would match.
default: msb = 0;
endcase

8.14. casez
Casez is the same as casex except only ? and z (not x) are used in the case choice constants as don’t cares. Casez is
favored over casex since in simulation, an inadvertent x signal, will not be matched by a 0 or 1 in the case choice.

Syntax Example 8 .13

same as for case statement casez (d)


(Section 8.10) 3’b1??: b = 2’b11; // b = 11 if d = 100 or greater
3’b01?: b = 2’b10; // b = 10 if d = 010 or 011
default: b = 2’b00;
endcase

Friday, January 05, 2001 9:34 pm 16 Peter M. Nyasulu


Introduction to Verilog

9. Timing Controls
9.1. Delay Control Not synthesizable
This specifies the delay time units before a statement is executed during simulation. A delay time of zero can also be
specified to force the statement to the end of the list of statements to be evaluated at the current simulation time.
Syntax Example 9 .1
#delay statement; #5 a = b + c; // evaluated and assigned after 5 time units
#0 a = b + c; // very last statement to be evaluated

9.2. Event Control, @


This causes a statement or begin-end block to be executed only after specified events occur. An event is a change in
a variable. and the change may be: a positive edge, a negative edge, or either (a level change), and is specified by the
keyword posedge, negedge, or no keyword respectively. Several events can be combined with the or keyword. Event
specification begins with the character @and are usually used in always statements. See page 18.
For synthesis one cannot combine level and edge changes in the same list.
For flip-flop and register synthesis the standard list contains only a clock and an optional reset.
For synthesis to give combinational logic, the list must specify only level changes and must contain all the variables
appearing in the right-hand-side of statements in the block.

Syntax Example 9 .2
@ (posedge variable or always
negedge variable) statement; @(posedge clk or negedge rst)
if (rst) Q=0; else Q=D; // Definition for a D flip-flop.
@ (variable or variable . . .) statement;
@(a or b or e); // re-evaluate if a or b or e changes.
sum = a + b + e; // Will synthesize to a combinational adder.

9.3. Wait Statement Not synthesizable


The wait statement makes the simulator wait to execute the statement(s) following the wait until the specified condi-
tion evaluates to true. Not supported for synthesis.
Syntax Example 9 .3
wait (condition_expression) statement; wait (!c) a = b; // wait until c=0, then assign b to a

9.4. Intra-Assignment Delay Not synthesizable


This delay #∆ is placed after the equal sign. The left-hand assignment is delayed by the specified time units, but the
right-hand side of the assignment is evaluated before the delay instead of after the delay. This is important when a
variable may be changed in a concurrent procedure. See also “Delay in Assignment (not for synthesis)” on page 12.
Syntax Example 9 .4
assign a=1; assign b=0;
variable = #∆t expression; always @(posedge clk)
b = #5 a; // a = b after 5 time units.
always @(posedge clk)
c = #5 b; /* b was grabbed in this parallel proce-
dure before the first procedure changed it. */

Friday, January 05, 2001 9:34 pm 17 Peter M. Nyasulu


Introduction to Verilog

10. Procedures: Always and Initial Blocks


10.1. Always Block
The always block is the primary construct in RTL modeling. Like the continuous assignment, it is a concurrent
statement that is continuously executed during simulation. This also means that all always blocks in a module execute
simultaneously. This is very unlike conventional programming languages, in which all statements execute sequen-
tially. The always block can be used to imply latches, flip-flops or combinational logic. If the statements in the
always block are enclosed within begin ... end, the statements are executed sequentially. If enclosed within the fork
... join, they are executed concurrently (simulation only).
The always block is triggered to execute by the level, positive edge or negative edge of one or more signals (sepa-
rate signals by the keyword or). A double-edge trigger is implied if you include a signal in the event list of the always
statement. The single edge-triggers are specified by posedge and negedge keywords.
Procedures can be named. In simulation one can disable named blocks. For synthesis it is mainly used as a com-
ment.

Syntax 1 Example 10 .1

always @(event_1 or event_2 or ...) always @(a or b) // level-triggered; if a or b changes levels


begin always @(posedge clk); // edge-triggered: on +ve edge of clk
... statements ...
end see previous sections for complete examples

Syntax 2

always @(event_1 or event_2 or ...)


begin: name_for_block
... statements ...
end

10.2. Initial Block


The initial block is like the always block except that it is executed only once at the beginning of the simulation. It is
typically used to initialize variables and specify signal waveforms during simulation. Initial blocks are not supported
for synthesis.

Syntax Example 10 .2

initial inital
begin begin
... statements ... clr = 0; // variables initialized at
end clk = 1; // beginning of the simulation
end

inital // specify simulation waveforms


begin
a = 2’b00; // at time = 0, a = 00
#50 a = 2’b01; // at time = 50, a = 01
#50 a = 2’b10; // at time = 100, a = 10
end

Friday, January 05, 2001 9:34 pm 18 Peter M. Nyasulu


Introduction to Verilog

11. Functions
Functions are declared within a module, and can be called from continuous assignments, always blocks or other func-
tions. In a continuous assignment, they are evaluated when any of its declared inputs change. In a procedure, they are
evaluated when invoked.
Functions describe combinational logic, and by do not generate latches. Thus an if without an else will simulate as
though it had a latch but synthesize without one. This is a particularly bad case of synthesis not following the simula-
tion. It is a good idea to code functions so they would not generate latches if the code were used in a procedure.
Functions are a good way to reuse procedural code, since modules cannot be invoked from a procedure.

11.1. Function Declaration


A function declaration specifies the name of the function, the width of the function return value, the function input
arguments, the variables (reg) used within the function, and the function local parameters and integers.

Syntax, Function Declaration Example 11 .1

function [msb:lsb] function_name; function [7:0] my_func; // function return 8-bit value
input [msb:lsb] input_arguments; input [7:0] i;
reg [msb:lsb] reg_variable_list; reg [4:0] temp;
parameter [msb:lsb] parameter_list; integer n;
integer [msb:lsb] integer_list; temp= i[7:4] | ( i[3:0]);
... statements ... my_func = {temp, i[[1:0]};
endfunction endfunction

11.2. Function Return Value


When you declare a function, a variable is also implicitly declared with the same name as the function name, and with
the width specified for the function name (The default width is 1-bit). This variable is “my_func” in Example 11 .1 on
page 19. At least one statement in the function must assign the function return value to this variable.

11.3. Function Call


As mentioned in Sect. 6.4. , a function call is an operand in an expression. A function call must specify in its terminal
list all the input parameters.

11.4. Function Rules


The following are some of the general rules for functions:
- Functions must contain at least one input argument.
- Functions cannot contain an inout or output declaration.
- Functions cannot contain time controlled statements (#, @, wait).
- Functions cannot enable tasks.
- Functions must contain a statement that assigns the return value to the implicit function name register.

Friday, January 05, 2001 9:34 pm 19 Peter M. Nyasulu


Introduction to Verilog

11.5. Function Example


A Function has only one output. If more than one return value is required, the outputs should be concatenated into
one vector before assigning it to the function name. The calling module program can then extract (unbundle) the indi-
vidual outputs from the concatenated form. Example 11.2 shows how this is done, and also illustrates the general use
and syntax of functions in Verilog modeling.
Syntax Example 11 .2
module simple_processor (instruction, outp);
function_name = expression input [31:0] instruction;
output [7:0] outp;
reg [7:0] outp;; // so it can be assigned in always block
reg func;
reg [7:0] opr1, opr2;

function [16:0] decode_add (instr) // returns 1 1-bit plus 2 8-bits


input [31:0] instr;
reg add_func;
reg [7:0] opcode, opr1, opr2;
begin
opcode = instr[31:24];
opr1 = instr[7:0];
case (opcode)
8’b10001000: begin // add two operands
add_func = 1;
opr2 = instr[15:8];
end
8’b10001001: begin // subtract two operands
add_func = 0;
opr2 = instr[15:8];
end
8’b10001010: begin // increment operand
add_func = 1;
opr2 = 8’b00000001;
end
default: begin; // decrement operand
add_func = 0;
opr2 = 8’b00000001;
end
endcase
decode_add = {add_func, opr2, opr1}; // concatenated into 17-bits
end
endfunction
// ----------------------------------------- ---------------------------------
always @(instruction) begin
{func, op2, op1} = decode_add (instruction); // outputs unbundled
if (func == 1)
outp = op1 + op2;
else
outp = op1 - op2;
end
endmodule

Friday, January 05, 2001 9:34 pm 20 Peter M. Nyasulu


Introduction to Verilog

12. Tasks Not Synthesizable


A task is similar to a function, but unlike a function it has both input and output ports. Therefore tasks do not return
values. Tasks are similar to procedures in most programming languages. The syntax and statements allowed in tasks
are those specified for functions (Sections 11).

Syntax Example 12 .1

task task_name; module alu (func, a, b, c);


input [msb:lsb] input_port_list; input [1:0] func;
output [msb:lsb] output_port_list; input [3:0] a, b;
reg [msb:lsb] reg_variable_list; output [3:0] c;
parameter [msb:lsb] parameter_list; reg [3:0] c; // so it can be assigned in always block
integer [msb:lsb] integer_list;
... statements ... task my_and;
endtask input[3:0] a, b;
output [3:0] andout;
integer i;
begin
for (i = 3; i >= 0; i = i - 1)
andout[i] = a[i] & b[i];
end
endtask

always @(func or a or b) begin


case (func)
2’b00: my_and (a, b, c);
2’b01: c = a | b;
2’b10: c = a - b;
default: c = a + b;
endcase
end
endmodule

Friday, January 05, 2001 9:34 pm 21 Peter M. Nyasulu


Introduction to Verilog

13. Component Inference


13.1. Latches
A latch is inferred (put into the synthesized circuit) if a variable is not assigned to in the else branch of an if ... else if
... else statement. A latch is also inferred in a case statement if a variable is assigned to in only some of the possible
case choice branches. Assigning a variable in the default branch avoids the latch. In general, a latch is inferred in if ...
else if ... else and case statements if a variable, or one of its bits, is only assigned to in only some of the possible
branches.
To improve code readability, use the if statement to synthesize a latch because it is difficult to explicitly specify the
latch enable signal when using the case statement.

Syntax Example 13 .1

See Sections 8.9 and 8.10 for always @(c, i); i D


if ... else if ... else and case statements begin; Q o
if (c == 1) c EN
o = i;
end

13.1. Edge-Triggered Registers, Flip-flops, Counters


A register (flip-flop) is inferred by using posedge or negedge clause for the clock in the event list of an always block.
To add an asynchronous reset, include a second posedge/negedge for the reset and use the if (reset) ... else statement.
Note that when you use the negedge for the reset (active low reset), the if condition is ( !reset).

Syntax Example 0 .1
always @(posedge clk or CLR
b
posedge reset_1 or always @(posedge clk); D
c
negedge reset_2) begin; Q a
begin a <= b & c;
clk CLK
if (reset_1) begin end
... reset assignments
end always @(posedge clk or rst
else if (!reset_2) begin negedge rst);
... reset assignments begin;
CLR
b D
end if (! rst) a< = 0;
else begin Q a
else a <= b;
...register assignments end clk CLK
end
end
Example 0 .2 An Enabled Counter
reg [7:0] count;
wire enable;
always @(posedge clk or posedge rst) // Do not include enable.
begin;
if (rst) count<=0;
else if (enable) count <= count+1;
end; // 8 flip-flops will be generated.

Friday, January 05, 2001 9:34 pm 22 Peter M. Nyasulu


Introduction to Verilog

13.2. Multiplexers
A multiplexer is inferred by assigning a variable to different variables/values in each branch of an if or case state-
ment. You can avoid specifying each and every possible branch by using the else and default branches. Note that a
latch will be inferred if a variable is not assigned to for all the possible branch conditions.
To improve readability of your code, use the case statement to model large multiplexers.

Syntax Example 13 .2
sel
See Sections 8.9 and 8.10 for if (sel == 1)
if ... else if ... else and case statements y = a; a
y
else
b
y = b;

case (sel) sel[1:0]


2’b00: y = a; a
2’b01: y = b; b
2’b10: y = c; y
c
default: y = d;
endcase d

13.3. Adders/Subtracters
The +/- operators infer an adder/subtracter whose width depend on the width of the larger operand.

Syntax Example 13 .3
sel
a
See Section 7 for operators if (sel == 1) c
y = a + b; sel + y
else b
y = c + d; d

13.4. Tri-State Buffers


A tristate buffer is inferred if a variable is conditionally assigned a value of z using an if, case or conditional operator.

Syntax Example 13.5

See Sections 8.9 and 8.10 for if (en == 1) en


if ... else if ... else and case statements y = a;
a y
else
y = 1’bz;

13.5. Other Component Inferences


Most logic gates are inferred by the use of their corresponding operators. Alternatively a gate or component may be
explicitly instantiated by using the primitive gates (and, or, nor, inv ...) provided in the Verilog language.

Friday, January 05, 2001 9:34 pm 23 Peter M. Nyasulu


Introduction to Verilog

14. Finite State Machines. For synthesis

When modeling finite state machines, it is recommended to separate the sequential current-state logic from the com-
binational next-state and output logic.

State Diagram Example 14 .1

for lack of space the outputs are not module my_fsm (clk, rst, start, skip3, wait3, Zot);
shown on the state diagram, but are: input clk, rst, start, skip3, wait3;
in state0: Zot = 000, output [2:0] Zot; // Zot is declared reg so that it can
in state1: Zot = 101, reg [2:0] Zot; // be assigned in an always block.
in state2: Zot = 111, parameter state0=0, state1=1, state2=2, state3=3;
in state3: Zot = 001. reg [1:0] state, nxt_st;

always @ (state or start or skip3 or wait3)


start=0
begin : next_state_logic //Name of always procedure.
reset=1 case (state)
state0: begin
state0 if (start) nxt_st = state1;
wait3=0 start=1 else nxt_st = state0;
end
state1: begin
nxt_st = state2;
state3
skip3=1 state1 end
state2: begin
wait3=1
if (skip3) nxt_st = state0;
skip3=0
else nxt_st = state3;
end
state2 state3: begin
if (wait3) nxt_st = state3;
else nxt_st = state0;
end
Using Macros for state definition default: nxt_st = state0;
As an alternative for- endcase // default is optional since all 4 cases are
parameter state0=0, state1=1, end // covered specifically. Good practice says uses it.
state2=2, state3=3; always @(posedge clk or posedge rst)
one can use macros. For example after the begin : register_generation
definition below 2'd0 will be textually if (rst) state = state0;
substituted whenever `state0 is used. else state = nxt_st;
`define state0 2'd0 end
`define state1 2'd1
`define state2 2'd always @(state) begin : output_logic
`define state3 2'd3; case (state)
state0: Zot = 3’b000;
When using macro definitions one must state1: Zot = 3’b101;
put a back quote in front. For example: state2: Zot = 3’b111;
case (state) state3: Zot = 3’b001;
`state0: Zot = 3’b000; default: Zot = 3’b000;// default avoids latches
`state1: Zot = 3’b101; endcase
`state2: Zot = 3’b111; end
`state3: Zot = 3’b001; endmodule

Friday, January 05, 2001 9:34 pm 24 Peter M. Nyasulu


Introduction to Verilog

14.1.

14.2. Counters
Counters are a simple type of finite-state machine where separation of the flip-flop generation code and the next-state
generation code is not worth the effort. In such code, use the nonblocking “<=” assignment operator.

Binary Counter Example 14 .2


Using toggle flip-flops reg [3:0] count; wire TC; // Terminal count (Carry out)
always @(posedge clk or posedge rset)
TC
begin
1T 1T 1T 1T if (rset) count <= 0;
C1 C1 C1 C1 else count <= count+1;
count[3] count[2]
count[1] count[0] end
CLK
assign TC = & count; // See “Reduction Operators” on page 7

14.3. Shift Registers


Shift registers are also best done completely in the flip-flop generation code. Use the nonblocking “<=” assignment
operator so the operators “<< N” shifts left N bits. The operator “>>N” shifts right N bits. See also Example 8 .3 on
page 13.

Shift Register Example 14 .3


reg [3:0] Q;
always @(posedge clk or posedge rset)
Q[3] Q[2] Q[1] Q[0]
1D 1D 1D 1D begin
C1 C1 C1 C1 if (rset) Q <= 0;
else begin
CLK
Q <=Q << 1; // Left shift 1 position
Q[0] <= Q[3]; /* Nonblocking means the old Q[3] is sent
to Q[0]. Not the revised Q[3] from the previous line.
end

Linear-Feedback Shift Register Example 14 .4


reg [3:0] Q;
always @(posedge clk or posedge rset)
Q[3] Q[2] Q[1] Q[0]
1D 1D 1D 1D begin
C1 C1 C1 C1 if (rset) Q <= 0;
else begin
CLK
Q <= {Q[2:1]: Q[3]^Q[2]; /* The concatenation operators
“{...}” form the new Q from elements of the old Q. */
end
end

Friday, January 05, 2001 9:34 pm 25 Peter M. Nyasulu


Introduction to Verilog

15. Compiler Directives


Compiler directives are special commands, beginning with ‘, that affect the operation of the Verilog simulator. The
Synopsys Verilog HDL Compiler/Design Compiler and many other synthesis tools parse and ignore compiler direc-
tives, and hence can be included even in synthesizable models. Refer to Cadence Verilog-XL Reference Manual for a
complete listing of these directives. A few are briefly described here.

15.1. Time Scale


`timescale specifies the time unit and time precision. A time unit of 10 ns means a time expressed as say #2.3 will
have a delay of 23.0 ns. Time precision specifies how delay values are to be rounded off during simulation. Valid
time units include s, ms, µs, ns, ps, fs.
Only 1, 10 or 100 are valid integers for specifying time units or precision. It also determines the displayed time units
in display commands like $display

Syntax Example 15 .1
`timescale 1 ns/1 ps // unit =1ns, precision=1/1000ns
`timescale time_unit / time_precision; `timescale 1 ns /100 ps // time unit = 1ns; precision = 1/10ns;

15.2. Macro Definitions


A macro is an identifier that represents a string of text. Macros are defined with the directive `define, and are invoked
with the quoted macro name as shown in the example.

Syntax Example 15 .2

`define macro_name text_string; `define add_lsb a[7:0] + b[7:0]


. . . `macro_name . . . assign 0 = 'add_lsb; // assign o = a[7:0] + b[7:0];

15.3. Include Directive


Include is used to include the contents of a text file at the point in the current file where the include directive is. The
include directive is similar to the C/C++ include directive.

Syntax Example 15 .3

`include file_name; module x;


'include “dclr.v”; // contents of file “dclr,v” are put here

Friday, January 05, 2001 9:34 pm 26 Peter M. Nyasulu


Introduction to Verilog

16. System Tasks and Functions


These are tasks and functions that are used to generate input and output during simulation. Their names begin with a
dollar sign ($). The Synopsys Verilog HDL Compiler/Design Compiler and many other synthesis tools parse and
ignore system functions, and hence can be included even in synthesizable models. Refer to Cadence Verilog-XL Ref-
erence Manual for a complete listing of system functions. A few are briefly described here.
System tasks that extract data, like $monitor need to be in an initial or always block.

16.1. $display, $strobe, $monitor


These commands have the same syntax, and display their values as text on the screen during simulation. They are
much less convenient than waveform display tools like cwaves or Signalscan. $display and $strobe display once
every time they are executed, whereas $monitor displays every time one of its parameters changes. The difference
between $display and $strobe is that $strobe displays the parameters at the very end of the current simulation time
unit. The format string is like that in C/C++, and may contain format characters. Format characters include %d (deci-
mal), %h (hexadecimal), %b (binary), %c (character), %s (string) and %t (time). Append b, h, o to the task name to
change default format to binary, octal or hexadecimal.

Syntax Example 16 .1
initial begin
$display (“format_string”, $displayh (b, d); // displayed in hexadecimal
par_1, par_2, ... ); $monitor (“at time=%t, d=%h”, $time, a);
end

16.2. $time, $stime, $realtime


These return the current simulation time as a 64-bit integer, a 32-bit integer, and a real number, respectively. Their
use is illustrated in Examples 4.6 and 13.1.

16.3. $reset, $stop, $finish


$reset resets the simulation back to time 0; $stop halts the simulator and puts it in the interactive mode where the
user can enter commands; $finish exits the simulator back to the operating system.

16.4. $deposit
$deposit sets a net to a particular value.

Syntax Example 16 .2

$deposit (net_name, value); $deposit (b, 1’b0);


$deposit (outp, 4’b001x);// outp is a 4-bit bus

16.5. $scope, $showscope


$scope(hierarchy_name) sets the current hierarchical scope to hierarchy_name. $showscopes(n) lists all modules,
tasks and block names in (and below, if n is set to 1) the current scope.

16.6. $list
$list (hierarchical_name) lists line-numbered source code of the named module, task, function or named-block.

Friday, January 05, 2001 9:34 pm 27 Peter M. Nyasulu


Introduction to Verilog

16.7. $random
$random generates a random integer every time it is called. If the sequence is to be repeatable, the first time one
invokes random give it a numerical argument (a seed). Otherwise the seed is derived from the computer clock.
Syntax Example 16 .3
reg [3:0] xyz;
xzz = $random[(integer)]; initial begin
xyz= $random (7); // Seed the generator so number
// sequence will repeat if simulation is restarted.
forever xyz = #20 $random;
// The 4 lsb bits of the random integers will transfer into the
// xyz. Thus xyz will be a random integer 0 ≤ xyz ≤ 15.

16.8. $dumpfile, $dumpvar, $dumpon, $dumpoff, $dumpall


These can dump variable changes to a simulation viewer like cwaves. The dump files are capable of dumping all the
variables in a simulation. This is convenient for debugging, but can be very slow.

Syntax Example 16 .4

$dumpfile(“filename.dmp”) // Test Bench


$dumpvar dumps all variables in the module testbench:
design. reg a, b; wire c;
$dumpvar(1, top) dumps all the varia- initial begin;
bles in module top and below, but not $dumpfile(“cwave_data.dmp”);
modules instantiated in top. $dumpvar //Dump all the variables
$dumpvar(2, top) dumps all the varia- // Alternately instead of $dumpvar, one could use
bles in module top and 1 level below. $dumpvar(1, top) //Dump variables in the top module.
$dumpvar(n, top) dumps all the varia- // Ready to turn on the dump.
bles in module top and n-1 levels below. $dumpon
$dumpvar(0, top) dumps all the varia- a=1; b=0;
bles in module top and all level below. topmodule top(a, b, c);
$dumpon initiates the dump. end
$dumpoff stop dumping.

16.9. $shm_probe, $shm_open


These are special commands for the Simulation History Manager for Cadence cwaves only. They will save variable
changes for later display.

Syntax Example 16 .5

$shm_open (“cwave_dump.dm”) // Test Bench


$shm_probe (var1,var2, var3); module testbench:
/* Dump all changes in the above 3 varia- reg a, b; wire c;
bles. */ initial begin;
$shm_probe(a, b, inst1.var1, inst1.var2); $shm_open(“cwave_data.dmp”);
/* Use the qualifier inst1. to look inside $shm_probe(a, b, c)
the hierarchy. Here inside module
instance “inst1” the variables var1 and /* See also the testbench example in “Test Benches” on p. 29
var2 will be dumped.*/

Friday, January 05, 2001 9:34 pm 28 Peter M. Nyasulu


Introduction to Verilog

17. Test Benches


A test bench supplies the signals and dumps the outputs to simulate a Verilog design (module(s)). It invokes the
design under test, generates the simulation input vectors, and implements the system tasks to view/format the results
of the simulation. It is never synthesized so it can use all Verilog commands.
To view the waveforms when using Cadence Verilog XL Simulator, use the Cadence-specific Simulation History
Manager (SHM) tasks of $shm_open to open the file to store the waveforms, and $shm_probe to specify the varia-
bles to be included in the waveforms list. You can then use the Cadence cwaves waveform viewer by typing cwaves
& at the UNIX prompt.

Syntax Example 17 .1
‘timescale 1 ns /100 ps // time unit = 1ns; precision = 1/10 ns;
$shm_open(filename); module my_fsm_tb; // Test Bench of FSM Design of Example 14.1
$shm_probe(var1, var2, ...) /* ports of the design under test are variables in the test bench */
reg clk, rst, start, skip3, wait3;
Note also wire Button;
var=$random
wait(condition) statement /**** DESIGN TO SIMULATE (my_fsm) INSTANTIATION ****/
my_fsm dut1 (clk, rst, start, skip3, wait3, Button);

/**** SECTION TO DISPLAY VARIABLES ****/


initial begin
$shm_open(“sim.db”); //Open the SHM database file
/* Specify the variables to be included in the waveforms to be
viewed by Cadence cwaves */
$shm_probe(clk, reset, start);
// Use the qualifier dut1. to look at variables inside the instance dut1.
$shm_probe(skip3, wait3, Button, dut1.state, dut1.nxt_st);
end

/**** RESET AND CLOCK SECTION ****/


initial begin
clk = 0; rst=0;
#1 rst = 1; // The delay gives rst a posedge for sure.
#200 rst = 0; // Deactivate reset after two clock cycles +1 ns*/
end
always #50 clk = ~clk; // 10 MHz clock (50*1 ns*2) with 50% duty-cycle

/**** SPECIFY THE INPUT WAVEFORMS skip3 & wait3 ****/


initial begin
skip3 = 0; wait3 = 0; // at time 0, wait3=0, skip3=0
#1; // Delay to keep inputs from changing on clock edge.
#600 skip3 = 1; // at time 601, wait3=0, skip3=1
#400 wait3 = 1; // at time 1001, wait3=1, skip3=0
skip3= 0;
#400 skip3 = 1; // at time 1401, wait3=1, skip3=1
wait(Button) skip3 = 0; // Wait until Button=1, then make skip3 zero.
wait3 = $random; //Generate a random number, transfer lsb into wait3
$finish; // stop simulation. Without this it will not stop.
end
endmodule

Friday, January 05, 2001 9:34 pm 29 Peter M. Nyasulu


Introduction to Verilog

17.1. Synchronous Test Bench


In synchronous designs, one changes the data during certain clock cycles. In the previous test bench one had to keep
counting delays to be sure the data came in the right cycle. With a synchronous test bench the input data is stored in a
vector or array and one part injected in each clock cycle. The Verilog array is not defined in these notes.
Synchronous test benches are essential for cycle based simulators which do not use any delays smaller than a clock
cycle.

Things to note: Example 17 .2


data[8:1]=8'b1010_1101;
The underscore visually separates the // Synchronous test bench
bits. It acts like a comment. module SynchTstBch:
reg [8:1] data;
if (I==9) $finish; reg x,clk;
When the data is used up, finish integer I;

x<=data[I]; I<=I+1; initial begin


When synthesizing to flip-flops as in an data[8:1]=8'b1010_1101; // Underscore spaces bits.
In an @(posedge... procedure, I=1;
always use nonblocking. Without that x=0;
you will be racing with the flip-flops in clk=0;
the other modules. forever #5 clk=~clk;
end
/*** Send in a new value of x every clock cycle***/
always @(posedge clk)
begin
if (I==9) $finish;
#1; // Keeps data from changing on clock edge.
x<=data[I];
I<=I+1;
end
topmod top1(clk, x);

endmodule

Friday, January 05, 2001 9:34 pm 30 Peter M. Nyasulu


Yaswanth B
8/11/23

VERILOG INTRODUCTION
What is Verilog?
Verilog is a hardware description language (HDL) that is used to describe digital systems and circuits in the form
of code. It was developed by gateway design automation in the mid-1980s and later acquired by Cadence Design
Systems.

Verilog is widely used for the design and verification of digital and mixed-signal systems, including both
Application-Specific Integrated Circuits (ASICs) and Field-Programmable Gate Arrays (FPGAs). It supports a range
of levels of abstraction, from structural to behavioral, and is used for both Simulation-Based Design and
Synthesis-Based Design.

The language is used to describe digital circuits hierarchically, starting with the most basic elements such as logic
gates and flip-flops, and building up to more complex functional blocks and systems. It also supports a range of
modeling techniques, including Gate-level, RTL-level, and Behavioral-level modeling.

What was used before Verilog?


Before the development of Verilog, the primary Hardware Description Language (HDL) used for digital circuit
Design and Verification was VHDL (VHSIC Hardware Description Language). VHDL was developed in the 1980s by
the U.S. Department of Defense as part of the very high-speed integrated circuits (VHSIC) program to design and
test high-speed digital circuits.

VHDL is a complex language that enables designers to describe digital systems using a range of abstraction levels,
from the low-level transistor and gate levels up to complex hierarchical systems. It was designed to be more
descriptive and flexible than earlier HDLs, such as ABEL (Advanced Boolean Expression Language), ISP (Integrated
System Synthesis Procedure), and CUPL (Compiler For Universal Programmable Logic).

Abstraction levels:
Verilog supports a design at many levels of abstraction, such as:

o Behavioral level
o Register-transfer level
o Gate level

Behavioral level

The behavioral level describes a system by concurrent algorithms behavioral. Every algorithm is sequential,
which means it consists of a set of executed instructions one by one. Functions, tasks, and blocks are the main
elements. There is no regard for the structural realization of the design.

Register-Transfer Level

Designs using the Register-Transfer Level specify a circuit's characteristics using operations and the transfer of
data between the registers.

The modern definition of an RTL code is "Any code that is synthesizable is called RTL code".

Gate Level

The characteristics of a system are described by logical links and their timing properties within the logical level.
All signals are discrete signals. They can only have definite logical values (`0', `1', `X', `Z`).

1|Page
Yaswanth B
8/11/23

The usable operations are predefined logic primitives (basic gates). Gate-level modeling may not be the right
idea for logic design. Gate-level code is generated using tools such as synthesis tools, and his netlist is used for
gate-level simulation and backend.

Gate-level modeling exhibits two properties :


Drive strength − The strength of the output gates is defined by drive strength. The output is strongest if there is
a direct connection to the source. The strength decreases if the connection is via a conducting transistor and
least when connected via a pull-up/down resistive. The drive strength is usually not specified, in which case the
strengths default to strong1 and strong0.
Delays − If delays are not specified, then the gates do not have propagation delays; if two delays are specified,
then the first one represents the rise delay and the second one, fall delay; if only one delay is specified, then
both, rise and fall are equal. Delays can be ignored in synthesis.
Gate Primitives
The basic logic gates using one output and many inputs are used in Verilog. GATE uses one of the keywords -
and, nand, or, nor, xor, xnor for use in Verilog for N number of inputs and 1 output.
Transmission Gate Primitives
Transmission gate primitives include both, buffers and inverters. They have single input and one or more
outputs. In the gate instantiation syntax shown below, GATE stands for either the keyword buf or NOT gate.
Example: Not, buf, bufif0, bufif1, notif0, notif1
Not – n outout inverter
Buf – n output buffer
Bufifo – tristate buffer, active low enable
Bufif1 – tristate buffer, active high enable
Notifo – tristate inverter, active low enable
Notif1 – tristate inverter, active high enable

Language Concepts:

• Concurrency:
HDL supports concurrency and includes the notion of time. The notion of time deals with the delays of
the circuit. In real-time we have delays in the circuit design and HDL consists of the delays. Concurrency
is nothing but the parallel execution of two events or statements. In C or C++ Language, we don’t have
concurrency i.e., they are sequential in nature.
• Structural:
The structural features of Verilog HDL also allow you to design circuits by instantiating pre-defined
primitives such as gates, registers and Xilinx-specific primitives like CLKDLL and BUFGs. These primitives
are other than those included in the Verilog language.
• Timing:
delay-based timing control can be specified by a number, identifier, or a mintypmax_expression
• Procedural statement:
These are procedural statements that allow expressions to be continuously assigned to variables or
nets.

2|Page
Yaswanth B
8/11/23

Hierarchical design:

Verilog is like any other hardware description language. It permits the designers to design the designs in either
a Bottom-up or Top-down methodology.

o Bottom-Up Design: The traditional method of electronic design is bottom-up. Each design is performed
at the gate-level using the standards gates. This design gives a way to design new structural, hierarchical
design methods.
o Top-Down Design: It allows early testing, easy change of different technologies, and structured system
design and offers many other benefits.

Lexical Tokens
Verilog language source text files are a stream of lexical tokens. A token consists of one or more characters, and
each single character is in exactly one token.
The basic lexical tokens used by the Verilog HDL are similar to those in C Programming Language. Verilog is case-
sensitive. All the keywords are in lower case.
White Space
White spaces can contain characters for spaces, tabs, new lines and form feeds. These characters are ignored
except when they serve to separate tokens.
White space characters are Blank space, Tabs, Carriage returns, New lines, and Form feeds.
Comments
There are two forms to represent the comments
• 1) Single-line comments begin with the token // and end with a carriage return.
Ex.: //this is single-line syntax

• 2) Multiline comments begin with the token /* and end with token */
Ex.: /* This is multiline Syntax*/
Numbers
You can specify a number in binary, octal, decimal, or hexadecimal format. Negative numbers are represented
in 2’s complement numbers. Verilog allows integers, real numbers, and signed & unsigned numbers.
The syntax is given by − <size> <radix> <value>
Size or unsized number can be defined in <Size> and <radix> defines whether it is binary, octal, hexadecimal, or
decimal.
Identifiers
Identifier is the name used to define the object, such as a function, module, or register. Identifiers should begin
with alphabetical characters or underscore characters.
Ex. A_Z, a_z,_
Identifiers are a combination of alphabetic, numeric, underscore, and $ characters. They can be up to 1024
characters long.
Operators

3|Page
Yaswanth B
8/11/23

Operators are special characters used to put conditions or to operate the variables. There are one, two, and
sometimes three characters used to perform operations on variables.
Ex. >, +, ~, &! =.
Verilog Keywords
Words that have special meaning in Verilog are called the Verilog keywords. For example, assign, case, while,
wire, reg, and, or, nand, and module. They should not be used as identifiers. Verilog keywords also include
compiler directives, and system tasks and functions.

Module & Instantiation of Instances

A Module in Verilog is declared within the pair of keywords module and endmodule.

Following the keyword module are the module name and port interface list.

module my_module ( a, b, c, d );

input a, b;

output c, d;

...

endmodule

All instances must be named except the instances of primitives. Only primitives in Verilog can have anonymous
instances, i.e. and, or, nand, nor, xor, xnor, buf, not, bufif1, bufi0, notif1, notif0, nmos, pmos, cmos, tran, tranif1,
tranif0, rnmos, rpmos, rcmos, rtran, rtranif1, rtranif0.

Port Connections at Instantiations

In Verilog, there are 2 ways of specifying connections among ports of instances.

a) By ordered list (positional association) This is the more intuitive method, where the signals to be connected
must appear in the module instantiation in the same order as the ports listed in module definition.

b) By name (named association) When there are too many ports in the large module, it becomes difficult to track
the order. Connecting the signals to the ports by the port names increases readability and reduces possible
errors.
module top;

reg A, B;

wire C, D;

my_module m1 (A, B, C, D);

// By order my_module m2 (.b(B), .d(D), .c(C), .a(A)); // By name

...

endmodule

4|Page
Yaswanth B
8/11/23

Interview questions:
1. What is the abstraction level of the test bench?
2. Difference between RTL and Behavioral code?
3. Does it matter to include the ports in the module declaration?
4. Which abstraction level is the lowest one and why?
5. What is the difference between C and Verilog?
6. What is the difference between VHDL and Verilog?
7. How Verilog is different from C and C++?
8. What are the features of VHDL?
9. What is PLI?
10. What is Verilog used for?
11. What software is used for Verilog?
12. What is RTL in Verilog?

5|Page
YASWANTH B
8/12/23
DAY-2

DATA TYPES:
A storage format having a specific range or type is called data type.
Verilog supports 4 types of logic values as

In Verilog, data types are divided into NETS and Registers. These data types differ in how they are
assigned and hold values and represent different hardware structures.

• NETS:
▪ Wire
▪ WAND
▪ WOR
▪ Trireg
• Registers:
▪ Reg
▪ Integer
▪ Real
▪ Time

NETS:

• the nets variables represent the physical connection between structural entities.
• These variables do not store values (except trireg)
• They have the value of their driver which changes continuously by the driving circuit.
• Can’t be used as the left-hand side of a procedural block i.e., always and initial.
• Some net data types are wire, tri, wor, trior, wand, triand, tri0, tri1, supply0, supply1 and
trireg.
• A net data type must be used when a signal is:
▪ Driven by the output of some device.
▪ Declared as an input or in-out port.
▪ On the left-hand side of a continuous assignment.

Page | 1
YASWANTH B
8/12/23
DAY-2

Wire:
Wires, specified with the wire keyword represent physical wires that carry electrical signals from one
module to the next. Wires do not store any data; they must be constantly supplied with a value or
will not contain a value. Wires may not be the target of a blocking or sequential assignment.
Wires come in one of three varieties:

wire These wires carry simple data from one port to another.

These wires are a logical OR of all input data values applied to the wire.
wor
These synthesize to OR gates with multiple input ports.

These wires are a logical AND of all input data values applied to the wire.
wand
These synthesize to AND gates with multiple input ports.

Wires can be assigned a value using the assign keyword. All assign declarations are considered to be
running concurrently and continuously.
In the following case, the value of a is dependent on the values of b and c. Any change in
either b or c will result in an automatic and instantaneous change in the value of a.

wire a, b, c;
assign a = b & c;

Circular assignments cannot be made using the assign keyword, as this produces a continuous loop.
In the following example, the value of a is undefined, because it depends on itself passed through
combinational (i.e. asynchronous, continuously operating) logic.

wire a, b;
assign a = a | b;

For the wand and wor data types, all assignments to that wire are considered to be ports to logic
gates. For instance, the following code:

wire a, b, c;
wor x;
assign x = a;
assign x = b;
assign x = c;

Page | 2
YASWANTH B
8/12/23
DAY-2

Is equivalent to this code:

wire a, b, c, x
assign x = (a | b | c);

While it may seem like more work to use wor or wand, they can greatly simplify some complicated
logic operations, and they can help to improve the readability of the code.

The truth table of Wand and Wor:

Wand 0 1 X Z Wor 0 1 X Z
0 0 0 0 0 0 0 1 X 0
1 0 1 X 1 1 1 1 1 1
X 0 X X X X X 1 X X
Z 0 1 X Z Z 0 1 X Z

Trireg:

It stores a value and is used to model charge storage nodes.

It has two states:

• Driven State: when atleast one driver of a trireg has a value of 1,0 or X that values propagation
into the trireg and is the trireg driven values.
• Capacitive state: when all the drivers of a trireg net at the high impedance value (Z). the trireg
net retains its last driven value and behaves like a reg data type.

REGISTERS:

A register, denoted with the keyword reg is a memory storage location. Registers store values
without needing constant assignment, but they must be manually updated with a blocking or
sequential assignment. Register values are all treated as unsigned values, and any extension of a
value into a larger register will not result in logical sign extension.
Registers can be used with the "=" and "<="

b <= y + z;

The use of blocking assignments generates additional storage and timing circuitry in a synthesized
design. These assignments should not be used if they are not needed because of the additional need
for resources.

Page | 3
YASWANTH B
8/12/23
DAY-2

Assignments with the "=" operator are blocking assignments, and they will be performed
sequentially. Assignments with the "<=" operator are non-blocking. All non-blocking assignments in a
particular code block will begin at the same time. The block will not terminate until all the non-
blocking assignments have been completed.

Vectors

a vector is collection of a variables denoted with the same name but with different subscripts
example: [2:0]i;

assign y=i[2]^i[1];
assign y=i[1]^i[0];
endmodule

integer:

Integer values, specified with the integer keyword are similar in function to registers, except that they
are treated implicitly as signed numbers. Integer values will be logically sign-extended on the
assignment.

Real

The real data types can be constants or real register data types. They are declared using the
‘real’ keyword.

The real value is rounded off if they are assigned to an integer data type,
A real number can be specified in one of the following two forms.

1. decimal notation: examples of numbers in this form are: 2.0, 5.678, 1154.76, 0.1
2. scientific notation: examples of numbers in this form are:

23_5.1e2 23510.0 (underscores are ignored)


3.6e2 360.0 (e and E are the same)
5E-4 0.0005

Parameter

A parameter is similar to predefined identifiers in C. It is used to declare a global constant

example: parameter u=8;

Page | 4
YASWANTH B
8/12/23
DAY-2

Buses

Register and wire types can be specified as multi-bit buses. This assignment is made in the variable
declaration using the [] operator. As an example:

wire [5:0] a;

This declares wire a to be a bus of 6 wires, with bit 5 (a[5]) being the MSB, and bit 0 (a[0]) being the
LSB. The bit number of the LSB must be lower than the bit number for the MSB, but it needs not be
zero.
Bit Selection

The individual wires or registers in a bus can be interfaced with directly, and subsets of the bus can
be manipulated. Given the following declaration:

wire [15:0] a;

The following code will set a value to bit 14 of the bus:

assign a[14] = 1'b1;

And the following code will assign a value to the lower 8 bits of the bus:

assign a[7:0] = 8'b01101101;

Likewise, we can read from only part of a bus. The following code assigns the 8-bit bus b to be the
upper 8 bits of the 16-bit bus a:

wire [15:0] a;
wire [7:0] b;
assign b[7:0] = a[15:8];

Part-select operators let the compiler calculate the range based on a starting point and a data-width
size;

wire [15:0] a;
wire [7:0] b;
assign b[7:0] = a[15:8];
assign b[7:0] = a[8+:8]; // equivalent
assign b[7:0] = a[15-:8]; // equivalent

Page | 5
YASWANTH B
8/12/23
DAY-2

String
An ordered collection of characters is called a string. They can be stored in reg data type. Each
character in a string requires 1 byte (8 bits) for storage and is typically mentioned within double
quotes (” “).
reg [8*11:0] name = "Hello World"; // String "Hello World"

//requires 11 bytes space.

Time
Verilog provides a time register to store simulation time. A time register is declared using the ‘time’
keyword and it has a width of at least 64 bits depending on the simulator and machine used.
time curr_time; // curr_time is a time variable.

Arrays
Verilog allows arrays of reg, time, integer, and vector register data types.
Example:
integer count [0:5];

count[2] // To access 2nd element in an array

integer two_D_arr [3:0][3:0]; // illegal

time timestamp[1:5]; // array of 5 timestamp variables.

reg [3:0] var[0:7]; // Array of 8 var and each var has 4 as bit width

Note:
1. Verilog does not allow the use of multidimensional arrays.
2. Arrays for real variables are also not allowed in Verilog.

Memories
Verilog provides a facility to model register memories like ROM or RAM as an array of registers. Each
array element in an array is called a word.
reg mem [0:511]; // Memory mem with 512 1-bit word.

reg [3:0] mem [0:511]; // Memory mem with 512 4-bit words

Page | 6
YASWANTH B
8/12/23
DAY-2

Defaults values of data types:

1. Wire - High Impedance (z)

2. Reg – Unknown (x)

3. Integer – Unknown (x)

4. Real – 0.0

5. Time – Unknown (x)

Synthesizable Non-Synthesizable
Wire, wor, wand Trireg
Reg , integer. Time, real

Implicit net declaration Without declaration we can use it but it should be one bit.

Interview questions:
1. What are the data types in Verilog?
2. What does wire refer to?
3. What is reg in Verilog?
4. What is the main difference between wire and reg?
5. Write the alternative declaration of bytes?
6. What is a parameter?
7. What is the odd man out in the following Verilog HDL data type?
1) wand 2) wor 3) tri 4) reg

--------------------------------------------------------------------------------------------------------------------------------------

Page | 7
YASWANTH B
8/12/23
DAY-2

Day-1 Solutions:

1. What is the abstraction level of the test bench?

Sol: behavioral level

2. Difference between RTL and Behavioral code?

Sol: The behavioral model always uses blocks with procedural statements, while the RTL model uses
continuous assignments that begin with the keyword 'assign'
Behavioral code is higher-level and usually can't be synthesized. Constructs like loops, delays,
and "initial" statements are behavioral. RTL code is lower-level and is intended to be
synthesized. It defines a circuit as a combination of interconnected registers and the operations
performed on signals between those registers.

3.Does it matter to include the ports in the module declaration?

Sol: yes, Ports, also referred to as pins or terminals, are used when wiring the module to other
modules.

4.Which abstraction level is the lowest one and why?

Sol: gate level, this is the lowest level of abstraction. Here the circuit is described by logical links and
their timing properties

5. What is the difference between C and Verilog?

Page | 8
YASWANTH B
8/12/23
DAY-2

6. What is the difference between VHDL and Verilog?

7.What are the features of VHDL?

Sol: VHDL supports the following features:

1) Design methodologies and their features.


2) sequential and concurrent activities.
3) design exchange
4) standardization
5) documentation

8.What is PLI?

Sol: It is the Programming Language Interface used for enabling C programming in Verilog. It
performs multiple tasks

• Passing data

• Altering and returning object value in the design hierarchy

• Accessing simulator database

• Monitoring alterations in the design hierarchy

Page | 9
YASWANTH B
8/12/23
DAY-2

9. What is Verilog used for?

Verilog is the most Popular Hardware Description Language for a digital system. Any system
like Microprocessor, memory network switch or Flip flop Can be described using this
technology.

Page | 10
Que 1) What is the purpose of the "automatic" data type in Verilog tasks and functions?

In Verilog, the automatic data type is used in tasks and functions to create automatic local
variables

automatic variables are temporary and created anew each time the task or function is called.

This makes them useful for holding temporary values that are required only within the scope
of the task or function.

syntax for using the automatic data type in a task or function:

task automatic my_task;

automatic data_type variable_name;

// Task body...

endtask

function automatic return_type my_function;

automatic data_type variable_name;

// Function body...

return value;

endfunction

Example:
module AutomaticExample;

task automatic my_task;


automatic integer count = 0;

count = count + 1;
$display("Task Call %d: Count = %d", $time, count);
endtask

function automatic integer my_function;

automatic integer result = 42;


result = result * 2;
return result;
endfunction

initial begin

my_task; // Call the task multiple times


my_task;
my_task;

integer result;

result = my_function(); // Call the function and store the result


$display("Result of Function: %d", result);
end
endmodule

Que 2) What are the different ways to assign values to an array in Verilog?

Element-wise assignment using indexed assignment:

This method is used to assign values to individual elements of an array.

array_name[index] = value;
Example:

reg [7:0] my_array [0:3];


my_array[0] = 8'b10101010;
my_array[1] = 8'b11001100;
my_array[2] = 8'b11110000;
my_array[3] = 8'b00110011;

Array assignment using curly braces:

This method is used to assign values to all elements of an array in a single line.

array_name = '{value1, value2, ..., valueN};


Example :

reg [7:0] my_array [0:3];


my_array = '{8'b10101010, 8'b11001100, 8'b11110000, 8'b00110011};

Using a for loop to assign values:


This method is used when you want to initialize an array using a loop, especially for large
arrays or when the values follow a specific pattern.

reg [7:0] my_array [0:15];


integer i;
for (i = 0; i < 16; i = i + 1) begin

my_array[i] = i; // Assign values from 0 to 15


end

Using a case statement:

reg [7:0] my_array [0:3];


integer selector = 2;

case (selector)
0: my_array = '{8'b10101010, 8'b11001100, 8'b11110000, 8'b00110011};
1: my_array = '{8'b11111111, 8'b00000000, 8'b01010101, 8'b10101010};
2: my_array = '{8'b00000000, 8'b11111111, 8'b10101010, 8'b01010101};
default: my_array = '{8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000};

endcase

Que 3) Explain the concept of "void" data type in Verilog.

the void data type represents the absence of a data type or the lack of a return value in tasks
and functions.

The void data type is typically used in tasks and functions that perform actions or procedures
but do not produce any result that needs to be stored or utilized further in the design.

the void data type is used in tasks and functions:

Void Task

task automatic my_task;


// Task body - no return value
Endtask

Void Function

function automatic void my_function;


// Function body - no return value
Endfunction

It simplifies the design and makes the code more readable by explicitly indicating that no
return value is expected.

Que 3) How do you create a multi-dimensional array in Verilog with a dynamic range?

In Verilog, we can create a multi-dimensional array with a dynamic range by using an


unpacked array and providing a dynamic range during declaration.

Unpacked arrays, also known as associative arrays or dynamic arrays.

data_type array_name [dynamic_range1][dynamic_range2];

Que 4) Describe the "function" data type in Verilog and its applications.

In Verilog, the function data type is used to define functions, which are blocks of procedural
code that can return a single value.

Applications:

Combinational Logic:

we can define a function to compute the output of a complex Boolean expression.

Value Transformations:

For instance, we can create a function to convert data from one format to another.

Look-Up Tables:

Parameterized Functions:

Functions can be parameterized, which means they can accept parameters to customize their
behavior.

Que 5) What is the significance of the "time" data type in Verilog?

The time data type in Verilog is used to represent time values in simulation.

it is a built-in data type specifically designed to model time-related quantities such as delays,
timing checks, and simulation time itself.

In Verilog, the time data type is a 64-bit signed integer that represents time in simulation
units

The smallest time unit in Verilog is typically one time unit (1s), and the default time precision
is usually in nanoseconds or picoseconds, depending on the simulator settings.

Modeling Delays:

Timing Checks: Verilog provides timing constructs like # (delay) and @ (wait) that use the
time data type.
Simulation Time: The time data type is used to represent the current simulation time.

the time data type in Verilog is essential for accurately modeling and simulating time-related
behavior in digital designs.

Que 6) How do you handle signed and unsigned arithmetic in Verilog?

Unsigned Arithmetic:

Data Types: Use reg , wire , or integer to represent unsigned values.

Operators: Use standard arithmetic operators like + , - , * , / , % , etc., to perform unsigned


arithmetic.

Rules: For reg and wire , make sure the widths of the operands are sufficient to hold the
results of the arithmetic operations.

Ex:

module UnsignedArithmeticExample;

reg [3:0] unsigned_a = 4'b1010;

reg [3:0] unsigned_b = 4'b0011;

reg [4:0] result_sum;

reg [4:0] result_product;

initial begin

result_sum = unsigned_a + unsigned_b; // 8 (4'b1010 + 4'b0011)

result_product = unsigned_a * unsigned_b; // 30 (4'b1010 * 4'b0011)

$display("Sum: %d, Product: %d", result_sum, result_product);

end

endmodule

Signed Arithmetic:

Data Types: Use reg signed or wire signed to represent signed values.

Operators: Use standard arithmetic operators like + , - , * , / , % , etc., to perform signed


arithmetic.

Rules: Signed arithmetic automatically takes care of sign extension and two's complement
representation.
Ex:

module SignedArithmeticExample;

reg signed [3:0] signed_a = 4'sb1010;

reg signed [3:0] signed_b = 4'sb1111;

reg signed [4:0] result_sum;

reg signed [4:0] result_product;

initial begin

result_sum = signed_a + signed_b; // -5 (4'sb1010 + 4'sb1111)

result_product = signed_a * signed_b; // -14 (4'sb1010 * 4'sb1111)

$display("Sum: %d, Product: %d", result_sum, result_product);

end

endmodule

Que 7) How do you create a parameterized packed array in Verilog?

Ex:

module ParameterizedPackedArray #(parameter WIDTH = 8);

// Declaration of a parameterized packed array

reg [WIDTH-1:0] my_array [0:3];

// Rest of the module...

// You can use the parameterized array in your design logic.

Endmodule

Que 8) How do you pass an array as an argument to a Verilog function?

Syntax:

function [return_type] function_name (data_type array_name [range]);

// Function body - contains procedural code that uses the array


return [result];

endfunction

Example:

module ArrayFunctionExample;

function automatic int sum_array_elements(int array[7:0]);

int i;

int sum = 0;

for (i = 0; i < 8; i = i + 1) begin

sum = sum + array[i];

end

return sum;

endfunction

reg [7:0] my_array [0:7];

integer result;

initial begin

my_array = '{8'h10, 8'h20, 8'h30, 8'h40, 8'h50, 8'h60, 8'h70, 8'h80};

result = sum_array_elements(my_array);

$display("Sum of array elements: %0d", result);

end

endmodule

Que 9) Describe the differences between "genvar" and "parameter" in Verilog.

genvar is a special variable used in generate blocks (generate /endgenerate ) to control loop
constructs, such as for and foreach loops,

genvar is local to generate blocks and cannot be accessed outside of them.

It has no data type; it is purely for loop control in generate blocks.


parameter is used to declare constant values with a fixed value at compile-time. It is typically
used to set configuration parameters, array sizes, or constant values used throughout the
design.

parameter is for compile-time constant values and cannot be changed during simulation
runtime.

It can be used at the module level, inside tasks, functions, and even in generate blocks (with
certain restrictions)

parameter can have any valid Verilog data type.

genvar is used for loop control within generate blocks to create multiple hardware instances
or perform iterative operations during elaboration.
@shraddha_pawankar Date 28/08/23

Que 1) What is the purpose of data types in Verilog?

Verilog datatypes define the type and size of variables, allowing proper storage and
manipulation of data.

// Declaration of variables with different data types

reg [7:0] data_reg; // 8-bit register

wire [15:0] data_wire; // 16-bit wire

int signed_num; // Signed integer variable

Que 2) Explain the difference between wire and reg data types in Verilog.

The "wire" data type is used for connecting different modules, representing interconnections
between hardware elements

It behaves like a continuous assignment and can't store data

he "reg" data type, on the other hand, can store values and simulate sequential behavior.

module WireAndRegExample(input a, input b, output wire y, output reg z);

assign y = a & b; // 'y' is a wire, used for continuous assignment.

always @(posedge clk) begin

z <= a | b; // 'z' is a register, storing data across clock cycles.

end

endmodule

Que 3) How do you define a variable of the integer data type in Verilog?

In Verilog, we can declare an integer variable using the "integer" keyword.

Que 4) What are the different scalar data types in Verilog?

Verilog has several scalar data types, such as "bit," "logic," "reg," "byte," "shortint," "int,"
"longint," "time,"

Que 5) Explain the differences between signed and unsigned data types in Verilog.

Signed data types can represent both positive and negative values, while unsigned data
types can only represent non-negative values.

Que 6) How do you declare a 2-dimensional array in Verilog?

In Verilog, we can declare a 2-dimensional array using the syntax: data_type array_name
[rows][columns];

module TwoDimensionalArrayExample;

reg [3:0] mem [7:0]; // 2D array with 8 rows and 4 columns


@shraddha_pawankar Date 28/08/23

initial begin

mem[0][0] = 8'd10; // Assign a value to the element in the first row, first
column

mem[1][2] = 8'd25; // Assign a value to the element in the second row, third
column

$display("mem[0][0]: %d, mem[1][2]: %d", mem[0][0], mem[1][2]);

end

endmodule

/* Output: mem[0][0]: 10, mem[1][2]: 25 */

Que 7) How can you declare a constant in Verilog?

In Verilog, we can declare a constant using the "parameter" or "localparam" keyword.

module ParameterExample;

parameter int SIZE = 8;

reg [SIZE-1:0] data;

initial begin

data = SIZE;

$display("Data: %d", data); // Output: "Data: 8"

end

endmodule

………………..

module LocalparamExample;

localparam int WIDTH = 4;

reg [WIDTH-1:0] signal;

initial begin

signal = WIDTH;
@shraddha_pawankar Date 28/08/23

$display("Signal: %d", signal); // Output: "Signal: 4"

end

endmodule

Que 8) Describe the usage of the "parameter" keyword in Verilog.

The "parameter" keyword in Verilog is used to declare constant values that can be assigned
during module instantiation.

Parameters are used to provide flexibility and configurability to modules without modifying
their internal code.

module ParameterExample #(

parameter int WIDTH = 8,

parameter int DEPTH = 16

)(

input logic [WIDTH-1:0] data_in,

output logic [WIDTH-1:0] data_out

);

// Some logic using 'WIDTH' and 'DEPTH' parameters

reg [WIDTH-1:0] memory [DEPTH-1:0];

always_ff @(posedge clk) begin

memory[0] <= data_in;

data_out <= memory[DEPTH-1];

end

endmodule

Que 9) What is the purpose of the "localparam" keyword in Verilog?

The "localparam" keyword in Verilog is used to declare constant values that are local to a
module or a specific block of code.

"localparam" cannot be overridden during module instantiation,


@shraddha_pawankar Date 28/08/23

module LocalparamExample;

localparam int MAX_COUNT = 10;

reg [3:0] count = 0;

always @(posedge clk) begin

if (count < MAX_COUNT)

count <= count + 1;

end

endmodule

Que 10) How do you define a user-defined data type in Verilog?

In Verilog, you can define a user-defined data type using the "typedef" keyword.

It allows you to create a new data type based on existing data types, making the code more
readable and modular.

typedef logic [7:0] data_byte_t;

typedef logic [15:0] data_word_t;

typedef logic [31:0] data_dword_t;

module UserDefinedTypeExample;

data_byte_t byte_data;

data_word_t word_data;

data_dword_t dword_data;

initial begin

byte_data = 8'hAA;

word_data = 16'hABCD;

dword_data = 32'hABCDEF01;

$display("byte_data: %h, word_data: %h, dword_data: %h", byte_data, word_data,


dword_data);

end
@shraddha_pawankar Date 28/08/23

endmodule

Que 11) How do you cast one data type into another in Verilog?

In Verilog, you can perform type casting using the curly braces {} syntax. Type casting is
particularly useful when you want to convert one data type into another to perform specific
operations.

module TypeCastingExample;

reg [3:0] a = 4'b1100;

reg [7:0] b;

logic [15:0] c;

initial begin

b = {a, 4'b0011}; // Casting 4-bit 'a' to 8-bit 'b' and appending 4'b0011

c = {b, 8'hFF}; // Casting 8-bit 'b' to 16-bit 'c' and appending 8'hFF

$display("a: %b, b: %b, c: %h", a, b, c);

end

endmodule

Que 16) Describe the concept of "bit" data type in Verilog

In Verilog, the "bit" data type is a single binary digit, representing either a 0 or a 1.

The "bit" type can be used for simple one-bit signals or flags.

module BitDataTypeExample;

bit single_bit = 1; // Declaring a 'bit' variable and assigning a value 1

initial begin

$display("Single bit value: %b", single_bit); // Output: "Single bit value: 1"

end

endmodule

"bit" is not used for multi-bit data representation; for that purpose, we would typically use
"logic" or "reg" data types, which can handle multiple bits.

Que 17) How do you perform arithmetic operations with different data types in Verilog?
@shraddha_pawankar Date 28/08/23

In Verilog, you can perform arithmetic operations on different data types by using type
casting or automatic type conversion

module ArithmeticExample;

reg [3:0] a = 4'b1010;

wire [3:0] b = 4'b0110;

reg [4:0] sum1;

reg [4:0] sum2;

reg [4:0] sum3;

// Automatic type conversion during arithmetic operations

assign sum1 = a + b; // 'a' and 'b' are 4-bit, result is automatically 5-bit

// Explicit type casting using the $signed system function

assign sum2 = $signed(a) + $signed(b); // Cast 'a' and 'b' to signed 5-bit and then add

// Explicit type casting using the $unsigned system function

assign sum3 = $unsigned(a) + $unsigned(b); // Cast 'a' and 'b' to unsigned 5-bit and then add

initial begin

$display("sum1: %b, sum2: %b, sum3: %b", sum1, sum2, sum3);

end

endmodule

Que 18) Explain the concept of "reg" and "wire" data types in Verilog.

In Verilog, both "reg" and "wire" are data types used to represent signals, but they have
different behavioral models and are used in different contexts

"reg" Data Type: The "reg" data type represents sequential behavior and is commonly used
to model flip-flops, registers, and other storage elements.

It holds its value across time steps, and assignments to "reg" variables are executed in
procedural blocks (always, initial).

"wire" Data Type:


@shraddha_pawankar Date 28/08/23

The "wire" data type represents combinational behavior and is used for interconnecting
different modules.

It represents continuous assignments and is used for connecting the outputs of one module
to the inputs of another.

module RegWireExample(

input wire a, b,

output reg y

);

// Combinational behavior using 'wire' type

wire w1, w2;

assign w1 = a & b;

assign w2 = ~w1;

// Sequential behavior using 'reg' type

always @(posedge clk) begin

if (reset) // Assuming 'reset' is an asynchronous active-low reset

y <= 1'b0;

else

y <= w2; // Sequential assignment using 'reg' type

end

endmodule

Que 19) Explain the concept of "casting" in Verilog and provide an example.

"casting" refers to the process of converting one data type into another explicitly.

Casting is particularly useful when we want to perform operations between variables of


different data types.

Verilog provides several casting operators to convert between different data types, such as
$signed , $unsigned , and the curly braces {} for concatenation.

module CastingExample;

reg [3:0] unsigned_data = 4'b1010;


@shraddha_pawankar Date 28/08/23

reg [4:0] signed_data;

initial begin

// Using $signed to cast 'unsigned_data' to signed and then subtract 5

signed_data = $signed(unsigned_data) - 5;

$display("unsigned_data: %b, signed_data: %b", unsigned_data, signed_data);

end

endmodule

Que 20) How do you declare a parameterized data type in Verilog?

We can declare a parameterized data type using the "typedef" keyword. Parameterized data
types allow you to create reusable type definitions that can be customized with different
parameter values.

module ParamDataTypeExample #(parameter WIDTH = 8);

typedef logic [WIDTH-1:0] data_type;

data_type reg_data; // Parameterized data type for register

data_type mem_data; // Parameterized data type for memory

initial begin

reg_data = 'hFF; // Assigning a value to 'reg_data'

$display("reg_data: %h", reg_data);

end

// Example of using parameterized data type in an array

data_type mem_array [0:15];

initial begin

mem_array[0] = 'h11; // Assigning a value to 'mem_array'

$display("mem_array[0]: %h", mem_array[0]);

end
@shraddha_pawankar Date 28/08/23

endmodule

Que 21) How do you specify the size of a data type dynamically in Verilog?

In Verilog, we cannot dynamically change the size of a data type at runtime. The size of a
data type in Verilog, such as reg, wire, or logic, is determined at compile time and remains
fixed throughout the simulation.

however, we can achieve dynamic sizing in Verilog using parameterized data types,

module ParamDataTypeExample #(parameter WIDTH = 8);

typedef logic [WIDTH-1:0] data_type;

data_type reg_data; // Parameterized data type for register

data_type mem_data; // Parameterized data type for memory

initial begin

reg_data = 'hFF; // Assigning a value to 'reg_data'

$display("reg_data: %h", reg_data);

end

// Example of using parameterized data type in an array

data_type mem_array [0:15];

initial begin

mem_array[0] = 'h11; // Assigning a value to 'mem_array'

$display("mem_array[0]: %h", mem_array[0]);

end

endmodule

Que 22) Explain the "enum" data type in Verilog and how it can be used.

In Verilog, the "enum" (enumeration) data type is used to create user-defined symbolic
constants, making the code more readable and manageable.
@shraddha_pawankar Date 28/08/23

To declare an enum, you use the typedef keyword and specify the possible values within
braces {} . By default, the enum values start from 0 and increment by 1 for each subsequent
value.

Que 23) How do you specify the size of a packed array in Verilog?

In Verilog, we can specify the size of a packed array using a constant value or a parameter.
Packed arrays are one-dimensional arrays where all elements have the same size, unlike
unpacked arrays where each element can have a different size.

To specify the size of a packed array, you use the [] syntax following the array name,
indicating the range of indices

module PackedArrayExample;

reg [7:0] packed_array [0:3]; // Packed array of 8-bit elements, size = 4

initial begin

packed_array[0] = 8'hFF; // Assign a value to the first element of the array

packed_array[1] = 8'hAA; // Assign a value to the second element of the array

$display("packed_array[0]: %h, packed_array[1]: %h", packed_array[0],


packed_array[1]);

end

endmodule

packed arrays are mainly used when you need to represent a set of same-sized elements, like
registers, memories, or signal buses.

Que 24) How do you use the "type" keyword to define a custom data type in Verilog?

there is no "type" keyword in Verilog used to define a custom data type.

The correct way to define custom data types in Verilog is to use the typedef keyword.

Que 25) How do you define a 2-dimensional packed array in Verilog?

reg [N-1:0] packed_array [M-1:0];

 N represents the bit-width of each element in the array.


 M represents the number of rows in the array.

This declaration creates a 2-dimensional packed array where each element has a
fixed size of N bits, and there are M rows.

module PackedArrayExample;
@shraddha_pawankar Date 28/08/23

reg [7:0] packed_array [3:0];

initial begin

// Assign values to the packed array elements

packed_array[0] = 8'b10101010;

packed_array[1] = 8'b11001100;

packed_array[2] = 8'b11110000;

packed_array[3] = 8'b00110011;

// Display the values of the packed array elements

$display("packed_array[0]: %b", packed_array[0]);

$display("packed_array[1]: %b", packed_array[1]);

$display("packed_array[2]: %b", packed_array[2]);

$display("packed_array[3]: %b", packed_array[3]);

end

endmodule

Que 26) Explain the "const" keyword with arrays in Verilog.

In Verilog, the const keyword is used to declare constant arrays.

A constant array is an array whose values cannot be changed or modified during simulation.
It allows you to create read-only arrays,

const data_type array_name [size] = '{value1, value2, ..., valueN};

 data_type is the data type of the array elements.


 array_name is the name of the constant array.
 size is the size of the array, indicating the number of elements.
 value1 , value2 , ..., valueN are the constant values assigned to the array
elements.
module ConstArrayExample;

const logic [3:0] my_const_array [3:0] = '{4'b0011, 4'b1100, 4'b0101, 4'b1010};

initial begin

// Try to modify the constant array (This will result in a compilation error)
@shraddha_pawankar Date 28/08/23

my_const_array[0] = 4'b1111;

end

endmodule

In this example, we declare a constant array named my_const_array , which is a 4-bit logic
vector. The array has four elements, and the values for each element are specified using the
constant values 4'b0011 , 4'b1100 , 4'b0101 , and 4'b1010 .

Output after simulation (if no compilation errors):

Error: Cannot assign to variable 'my_const_array'

The const keyword ensures that the array values remain constant and cannot be changed,
providing a way to define read-only data sets in your Verilog code.

Que 27) How do you use "typedef" to create a multidimensional array type in Verilog?
with examples

typedef to create a custom data type for a multidimensional array. By defining a custom data
type, you can improve the readability and maintainability of your code when working with
complex data structures

typedef data_type array_type[M1:M2][N1:N2];

 data_type is the data type of the array elements.


 array_type is the name of the custom data type for the multidimensional array.
 M1 , M2 , N1 , and N2 are the range specifiers for the array indices.

-----------

module MultidimensionalArrayExample;

typedef logic [7:0] data_type;

typedef data_type my_2D_array_type [0:1][0:2]; // Custom data type for 2D array

my_2D_array_type my_2D_array;

initial begin

my_2D_array[0][0] = 8'b10101010;

my_2D_array[0][1] = 8'b11001100;

my_2D_array[1][0] = 8'b11110000;
@shraddha_pawankar Date 28/08/23

my_2D_array[1][1] = 8'b00110011;

$display("my_2D_array[0][0]: %b", my_2D_array[0][0]);

$display("my_2D_array[0][1]: %b", my_2D_array[0][1]);

$display("my_2D_array[1][0]: %b", my_2D_array[1][0]);

$display("my_2D_array[1][1]: %b", my_2D_array[1][1]);

end

endmodule

Que 28) Explain the concept of "slicing" and "concatenation" with arrays in Verilog.

In Verilog, slicing and concatenation are operations used with arrays to extract specific
portions of an array or combine multiple arrays into a single one.

array_name[high_index:low_index]

 array_name : The name of the array from which you want to extract elements.
 high_index : The higher index indicating the most significant bit (MSB) of the
slice.
 low_index : The lower index indicating the least significant bit (LSB) of the slice.
reg [7:0] my_array = 8'b11001100;

// Slicing to extract bits 5 to 2 from my_array

reg [3:0] sliced_bits;

sliced_bits = my_array[5:2]; // sliced_bits will be 4'b0011

Syntax for concatenation:

{array1, array2, ..., arrayN}

reg [3:0] array1 = 4'b1100;

reg [2:0] array2 = 3'b101;

// Concatenating array1 and array2 to form a new array

reg [6:0] concatenated_array;

concatenated_array = {array1, array2}; // concatenated_array will be 7'b1100101

-------------------------------------------------------------------------------------------------------------------------------------
ARRAYS IN VERILOG

MEMORIES

1) Memories allocated in compilation time (Verilog)


 PACKED ARRAY
 UNPACKED ARRAY
(Multidimensional array)
2) Memory allocated during Run time (System verilog)
 DYNAMIC ARRAY
 QUEUES
 ASSOCIATIVE ARRAY

PACKED ARRAY:
 Size of packed array will be constant throughout simulation
 Size is determined before the variable name.
 One dimensional packed array called as vector

Ex:
bit [9:0] [8:0] mem
// here [9:0] is no. of groups and [8:0] no. of bits per group
bit [10] [4] mem;
//here 10 no. of groups and [4] is no. of bits per group
UNPACKED ARRAY:
 Size of array will be constant throughout the simulation
 Size is determined after the variable name
 Unpacked array is called array of array or multidimensional array.

Ex:

Bit[3:0][7:0] array [0:3]


// here [3:0] is 4 group per location
[7:0] is 8 bit each group
[0:3] is 4 memory location

Que 1) What is an array in Verilog, and what are its applications in hardware
design?
 Array is a collection of the same data type
 Arrays are used to store multiple values of the same data type and
provide organized way to access and manipulate data.
 They find extensive application in hardware design for tasks such as
representing memories,fifo,buffers.

Que 2) How do you access individual elements of a Verilog array? Provide an


example.
 Individual elements of a verilog array can be accessed using [] bracket.
 Verilog uses zero based indexing

Ex:

Myarray [2] // Third element of myarray.

Que 3) Describe the process of initializing a Verilog array with specific values.

 Verilog arrays can be initialized during declaration using ‘{ }’ syntax.

Ex: int array[3] = ‘{3,4,5] // single dimensional array


Int array [3] [2] = ‘{‘{1,2}, ‘{2,3},’{4,5}}// Two dimensional array

Que 4) Write Verilog code to implement a 2D unpacked array of 4x4 2-bit elements.

reg [1:0] my_array [0:3] [0:3];

Que 5) What is the purpose of using initial and always block with arrays?
 The initial block is used toperform one time initialization of arrays at the
beginning of simulation
 The always block is used to model sequential behavior

Que 6) Describe the use of looping constructs iterate through arrays in verilog

 For looping constructs we used for and foreach loop

Que 7) How can you parameterize the size of an array in verilog?


 We can use parameter or localparameters to make the array size configurable
 Parameters can be defined at the module level
 Localparam are declared within procedural block
--------------------------------------------------------------------------------------------------------------------------------------

Que 8) How can you use verilog arrays for hardware modelling ,like shift registers or
FIFOs?
 Arrays can be used to model shift registers,FIFO.

Que 9) What are the different types of memories you can implement using arrays in
verilog?
 Memories such as RAM,ROM,FIFO,SHIFT REGISTER.

Que 10) How do you use $urandom to initialize a random array in verilog testbenches?
We can us $urandom to initialize random array in verilog testbenches by calling inside initial
and always block
Ex:

initial

begin

for(int i=0;i< my_array.size();i++);

my_array[i] =$urandom;

end

EX:

module tb;
reg [5:0] a; //packed array
reg b [0:4]; //unpacked array

integer c[7:0]; //legal


//integer [31:0] d; //illegal

integer i;
initial

begin
for(i=0;i<8;i++)
begin
b[i] = $urandom;
$display("b[%0d]=%0d",i,b[i]);

end
end
initial
begin
a=6'b101011;

$display("A=%0d",a);
end
initial
begin
for(i=0;i<8;i++)
begin

c[i]=$urandom;
$display("c[%0d]=%0d",i,c[i]);
end
end
endmodule

https://www.edaplayground.com/x/JVBh

Que 11) How do you implement a circular buffer using a verilog array?
 A circular buffer can be implemented using an array along with read and write
pointers.
--------------------------------------------------------------------------------------------------------------------------------------

Que 12) What are the different methods to pass an array as an argument to a verilog
function or module?
 We can pass array as an argument to a verilog function or module using the input
and output keyword followed by the array

Que 13) How do you handle multi-dimensional arrays in verilog testbenches for stimulus
generation?
 For stimulus generation in testbenches,we can use nested loops to iterate though
elements of multidimensional array.

Example of packed array:

module mux(in,sel,out);

input sel;
input [1:0]in;
output out;

assign out= (!sel&in[0])|(sel&in[1]);


endmodule
@shraddha_pawankar date:26/07/23

Logical shift and arithmetical shift

Logical shift (Vacant bit filled with zero)


The purpose of a logical shift operation is to move the bits of a binary number left or right,
filling the empty bit positions with zeros, and effectively multiplying or dividing the number
by powers of 2.

Logical right shift

>> (Divide by 2)

Logical left shift

<< (Multiply by 2)

Arithmatic shift (vacant bit filled with MSB bit)


A logical shift treats the empty bit positions created during the shift by filling them with
zeros, regardless of the sign of the number being shifted.

Arithmatic right shift

>>>

Arithmatic left shift

<<<

Que 1) How are logical shifts used in unsigned number manipulation?

Logical shifts are commonly used in unsigned number manipulation,

such as setting, clearing,

or extracting specific bits,

and in bitwise rotation operations.

Que 2) What are the potential issues when using arithmetic shifts with signed integers?

The potential issues with arithmetic shifts arise when dealing with signed integers.

Right shifts may lose the least significant bits, leading to data loss,

while left shifts can cause overflow.

Que 3) Can you describe the importance of handling overflow and underflow in
arithmetic shifts?
@shraddha_pawankar date:26/07/23

Handling overflow and underflow is crucial in arithmetic shifts,

as left shifts can cause an overflow,

and right shifts can lead to underflow for negative numbers.

Que 4) How does the width of the data impact the shift operations?

The width of the data affects the shift operations by determining the number of bits involved
in the shift and the range of shift amounts.

Que 5) In which scenarios is an arithmetic shift more useful than a logical shift?

Arithmetic shifts are more useful than logical shifts in cases where signed number arithmetic
is required, such as multiplication or division.

Que 6) How do shifts affect the binary representation of a number?

Shifts affect the binary representation of a number by moving the bits left or right, effectively
scaling the number by powers of 2.

Que 7) How can logical and arithmetic shifts be achieved using bitwise operations?

Logical and arithmetic shifts can be achieved using bitwise operations, such as bitwise AND
and OR, combined with left or right shifts.

Que 8) Describe how shifts can be used to implement fast multiplication of unsigned
numbers.

Logical shifts can be used to efficiently multiply unsigned numbers by powers of 2.

Que 9) How can logical shifts be used to perform division of unsigned numbers?

Logical shifts can be used to perform division of unsigned numbers by powers of 2.

Que 10) Explain how logical shifts can be used in bit manipulation to set, clear, or
toggle specific bits.

Logical shifts are used in bit manipulation to set specific bits to 1,

clear specific bits to 0,

or toggle bits based on the desired operation.

Que 11) Describe the significance of shifts in bitwise rotation operations.

Shifts are significant in bitwise rotation operations, where bits are moved circularly, creating
rotation effects.

Que 12) Show an application of logical shifts in creating masks or extracting specific
data fields.

Logical shifts are used to create masks for extracting specific data fields from a binary
number.
@shraddha_pawankar date:26/07/23

Que 13) Implement a Verilog module for a logical left shift operation.

Ex:

module logical_left_shift#(parameter N=4)(d_in,shift_amount,d_out);

input [N-1:0] d_in;

input [4:0] shift_amount;

output [N-1:0] d_out;

assign d_out = d_in<< shift_amount;

endmodule

-----------------------------------------------------------------------------------------------------------------------------------
Que 14) Write a Verilog code to perform a logical right shift on an input data bus.

module logical_right_shift#(parameter N=4)(d_in,shift_amount,d_out);

input [N-1:0] d_in;

input [4:0] shift_amount;

output [N-1:0] d_out;

assign d_out = d_in >> shift_amount;

endmodule

Que 15) Describe a scenario where a logical shift operation might lead to unexpected
behavior.

A logical shift operation might lead to unexpected behavior when shifting negative numbers,
as it does not preserve the sign, potentially resulting in invalid results.

Que 16) Explain how shifts are involved in the generation of pseudo-random numbers.

Shifts play a crucial role in generating pseudo-random numbers by providing a mechanism


to introduce randomness through bitwise manipulation.

Que 17) How can you optimize the implementation of a shift operation for high-
performance systems?

We can use barrel shifter to reduce the latency.

Que 18) Implement a Verilog code for a dual-operation barrel shifter that supports
both left and right shifts.
@shraddha_pawankar date:26/07/23

A dual-operation barrel shifter supporting both left and right shifts could be designed by
implementing separate hardware paths for each direction with appropriate multiplexers for
selection.

------------------------------------------------------------------------------------------------------
-
@shraddha_pawankar Date:27/07/23

LOGICAL EQUALITY IN VERILOG

Logical equality ==

Logical inequality !=

1) Synthesizable
2) One of the operand has X and Z value result is unknown
3) X,z cannot merge with 0 & 1 result is ambiguous

CASE EQUALITY IN VERILOG

Case equality ===

Case inequality !==

1) Non synthesizable
2) If any of the operand has either x or z result is either true or false
3) Operator can merge with X and Z value.

Que 1) How do you perform logical equality comparison in Verilog?

module LogicalEqualityExample(input [3:0] a, input [3:0] b, output reg out);

always @*

out = (a == b);

endmodule

Que 2) How do you handle "don't care" conditions in Verilog when using case equality?

Using casez and casex

Que 3) Can you use case equality in a Verilog "always" block? Why or why not? with
examples

No, we cannot use case equality (casez and casex) directly inside a Verilog "always" block.
The reason is that the case equality constructs are meant for pattern matching and are
typically used outside of procedural blocks like "always" blocks.

Ex:

Incorrect Use of Case Equality in "always" Block

module IncorrectAlwaysBlockExample(input [1:0] sel, input [3:0] data, output reg [3:0] result);
@shraddha_pawankar Date:27/07/23

always @(sel, data)

casez(sel) // Incorrect use of case equality inside always block

2'b00? : result = data; // This will not work as intended

2'b01? : result = 4'b0001;

2'b10? : result = 4'b0010;

2'b11? : result = 4'b0011;

default: result = 4'b1111;

endcase

endmodule

Correct Use of "case" in "always" Block

module CorrectAlwaysBlockExample(input [1:0] sel, input [3:0] data, output reg [3:0] result);

always @(sel, data)

case(sel)

2'b00 : result = data; // Regular case statement for exact matching

2'b01 : result = 4'b0001;

2'b10 : result = 4'b0010;

2'b11 : result = 4'b0011;

default: result = 4'b1111;

endcase

endmodule

Note:

We cannot use case equality constructs (casez and casex) directly inside a Verilog "always" block.
Instead, use regular case statements or if-else statements for defining the procedural logic inside
an "always" block.

Case equality constructs are primarily used outside procedural blocks for pattern matching and
conditional assignments.

Que 4) How can you ensure proper handling of latches when using case equality in
Verilog?
@shraddha_pawankar Date:27/07/23

we can ensure proper handling of latches when using casez and casex in our Verilog designs.
Proper latch handling is essential to ensure predictable behavior and prevent unwanted latch
inference during synthesis.

Que 5) How do you handle multiple matches in a case equality construct in Verilog?

when using a case equality construct (casez or casex), we can have multiple patterns that
match the input condition

Example 1: casex with multiple matches

module MultipleMatchesExample(input [3:0] data, output reg [1:0] result);

always @*

casex(data)

4'b0000: result = 2'b00;

4'b0x01: result = 2'b01; // Multiple matches: 0001 and 0101

4'b10x0: result = 2'b10; // Multiple matches: 1000 and 1001

4'b1xxx: result = 2'b11; // Multiple matches: 1110 and 1111

default: result = 2'b00;

endcase

endmodule

Example 2: casez with multiple matches

module MultipleMatchesExample(input [3:0] data, output reg [1:0] result);

always @*

casez(data)

4'b0000: result = 2'b00;

4'b0?01: result = 2'b01; // Multiple matches: 0001 and 0101

4'b10?0: result = 2'b10; // Multiple matches: 1000 and 1001

4'b1???: result = 2'b11; // Multiple matches: 1110 and 1111

default: result = 2'b00;

endcase

endmodule

Que 6) Compare the use of case equality and conditional operator (?:) in Verilog code.

Both case equality constructs (casez and casex) and the conditional operator (?:)
@shraddha_pawankar Date:27/07/23

In Verilog are used for conditional assignments, but they serve different purposes and are
suitable for different scenarios

Case Equality (casez and casex):

Case equality constructs are primarily used for pattern matching and handling "don't care"
conditions in the input.

Conditional Operator (?:):

The conditional operator (?:) is used for simple conditional assignments based on a single
condition.

Que 7) Can you use case equality in Verilog for signed data types? Why or why not?

in Verilog, case equality constructs (casez and casex) can be used with signed data types, but
it's essential to understand their behavior and potential limitations.

When using case equality with signed data types, we need to consider the sign bit (most
significant bit).

Example:

module CaseEqualitySignedExample(input signed [3:0] data, output reg [1:0] result);

always @*

casez(data)

4'sb0000: result = 2'b00;

4'sb0x01: result = 2'b01; // Matches patterns 0001 and 0101

4'sb10x0: result = 2'b10; // Matches patterns 1000 and 1001

4'sb1xxx: result = 2'b11; // Matches patterns 1110 and 1111

default: result = 2'b00;

endcase

endmodule

the casez construct considers the sign bit as a regular bit, and it will perform pattern
matching based on its value.

Example: Using Regular Case Statements with Signed Data Types

module RegularCaseSignedExample(input signed [3:0] data, output reg [1:0] result);

always @*

case(data)

4'sb0000: result = 2'b00;


@shraddha_pawankar Date:27/07/23

4'sb0001: result = 2'b01;

4'sb0101: result = 2'b01;

4'sb1000: result = 2'b10;

4'sb1001: result = 2'b10;

4'sb1100: result = 2'b11;

4'sb1101: result = 2'b11;

default: result = 2'b00;

endcase

endmodule

result:

With regular case statements, you can differentiate between positive and negative values
and handle them independently based on their signed representation.

Que 8) Describe the differences between procedural and continuous assignments with
case equality.

Procedural Assignments:

Procedural assignments are used inside procedural blocks, such as "always" and "initial"
blocks.

Example: Procedural Assignment with Case Equality

module ProceduralAssignmentExample(input [1:0] sel, input [3:0] data, output reg [3:0]
result);

always @*

casez(sel)

2'b00? : result = data; // Matches 000x and 001x

2'b01? : result = 4'b0001; // Matches 010x and 011x

2'b1?? : result = 4'b0010; // Matches 10xx and 11xx

default: result = 4'b1111;

endcase

endmodule

we use a procedural "always @*" block to perform a case equality-based conditional


assignment to result based on the value of sel .

Continuous Assignments:
@shraddha_pawankar Date:27/07/23

Continuous assignments are used outside procedural blocks to specify continuous


assignments between signals. They are continuously active and drive the assigned values

Example: Continuous Assignment with Case Equality (Not Valid)

module ContinuousAssignmentExample(input [1:0] sel, input [3:0] data, output reg [3:0]
result);

// Incorrect continuous assignment with case equality

assign result = casez(sel)

2'b00? : data; // Matches 000x and 001x

2'b01? : 4'b0001; // Matches 010x and 011x

2'b1?? : 4'b0010; // Matches 10xx and 11xx

default: 4'b1111;

endcase

endmodule

To use case equality in continuous assignments, we can create separate continuous


assignments for each pattern match, but this may not be practical for complex patterns.

In such cases, it's better to use procedural assignments (inside "always" blocks) to handle
case equality-based conditional assignments.

Que 9) How do you handle floating-point numbers and real data types with case
equality in Verilog?

In Verilog, case equality constructs (casez and casex) are primarily designed for working with
vector data types, such as logic vectors and signed/unsigned integers.

They are not suitable for directly handling floating-point numbers or real data types

If we need to work with floating-point numbers or real data types in Verilog, we should use
standard arithmetic operations and comparison operators for conditional logic.

For example, we can use "if" statements or ternary operators (?:) to handle different cases
based on the value of floating-point numbers or real data types.

Example:

module FloatingPointExample(input real x, output real y);

always @*

y = (x > 0.0) ? (x * 2.0) : (x / 2.0);

endmodule
@shraddha_pawankar Date:27/07/23

Que 10) How can you ensure that your Verilog code is synthesizable when using case
equality constructs?

Verilog code is synthesizable when using case equality constructs (casez and casex) involves
following certain guidelines and best practices.

Use Complete Patterns: Make sure that each pattern in the case equality construct covers
all the bits relevant to that case. Avoid using incomplete patterns that may lead to latch
inference.

Avoid Overlapping Patterns: Ensure that the patterns in the case equality construct do not
overlap. Overlapping patterns may cause unintended behavior and synthesis issues.

Use Blocking Assignments: Inside the "always" block, use blocking assignments (=) when
working with combinational logic. This helps avoid unintentional latch inference.

Que 11) Compare the advantages and disadvantages of using nested if-else statements
versus case equality constructs.

Nested if-else statements and case equality constructs (casez and casex) are two different
approaches for implementing conditional logic in Verilog.

Advantages of Nested if-else Statements:

Flexibility

Readability

Ease of Modification

Example - Nested if-else Statements:

module NestedIfElseExample(input [1:0] sel, output reg [3:0] data_out);

always @*

begin

if (sel == 2'b00)

data_out = 4'b0000;

else if (sel == 2'b01)

data_out = 4'b0001;

else if (sel == 2'b10)

data_out = 4'b0010;

else if (sel == 2'b11)

data_out = 4'b0011;

else
@shraddha_pawankar Date:27/07/23

data_out = 4'b1111; // Unhandled case, default output

end

endmodule

Disadvantages of Nested if-else Statements:

Nested if-else statements are not well-suited for handling complex pattern matching
scenarios or "don't care" conditions, which case equality constructs handle more effectively.

Priority: Nested if-else statements rely on sequential evaluation. The first true condition
executes its associated block, and the rest of the conditions are not checked. This can lead to
different priority schemes depending on the order of conditions.

Advantages of Case Equality Constructs:

Pattern Matching: Case equality constructs (casez and casex) are designed for pattern
matching and handling "don't care" conditions. They provide a concise and readable
representation for handling multi-bit input patterns.

Priority: The order of patterns in the case equality construct defines their priority.

Example - Case Equality:

module CaseEqualityExample(input [1:0] sel, output reg [3:0] data_out);

always @*

casez(sel)

2'b00? : data_out = 4'b0000; // Matches 000x and 001x

2'b01? : data_out = 4'b0001; // Matches 010x and 011x

2'b1?? : data_out = 4'b0010; // Matches 10xx and 11xx

default: data_out = 4'b1111; // Unhandled case, default output

endcase

endmodule

Disadvantages of Case Equality Constructs:

Limited Complexity

Handling Overlapping Patterns

nested if-else statements are more suitable for complex conditions and offer greater
flexibility in implementing different operations based on various combinations of conditions.

Case equality constructs, on the other hand, are well-suited for pattern matching and
handling "don't care" conditions, but they may become less readable for complex scenarios.
@shraddha_pawankar Date:27/07/23

Q 12) Explain the concept of priority in case equality constructs and how to ensure
proper prioritization.

Example - Priority in Case Equality Constructs:

module PriorityExample(input [1:0] sel, output reg [3:0] data_out);

always @*

casez(sel)

2'b00? : data_out = 4'b0000; // Pattern 1

2'b01? : data_out = 4'b0001; // Pattern 2

2'b0?? : data_out = 4'b0010; // Pattern 3

2'b1?? : data_out = 4'b0011; // Pattern 4

default: data_out = 4'b1111; // Pattern 5 (Fallback/default case)

endcase

endmodule

 Pattern 1 (2'b00?) will match inputs "000x" and "001x".


 Pattern 2 (2'b01?) will match inputs "010x" and "011x".
 Pattern 3 (2'b0??) will match any "0" in the most significant bit and any value
for the least significant bit.
 Pattern 4 (2'b1??) will match any "1" in the most significant bit and any value
for the least significant bit.
 Pattern 5 (default) will act as a fallback case and will match any unhandled
conditions.

 With this ordering, if sel is "0000", it will match Pattern 1, and data_out will be
set to "0000". Similarly, if sel is "0110", it will match Pattern 2, and data_out will
be set to "0001". If sel is "01xx", it will still match Pattern 2 because it's more
specific than Pattern 3.

 Proper prioritization is important to ensure that the desired behavior is


achieved when using case equality constructs.

Que 13) Explain the difference between logical equality (==) and bitwise equality
(===) operators in Verilog.

In Verilog, there are two different equality operators: logical equality (==) and bitwise equality
(=== ).

Logical Equality (==) Operator:


@shraddha_pawankar Date:27/07/23

The logical equality operator (==) is used for comparing scalar and vector data types.

When comparing vectors, it performs a logical comparison, meaning it checks if all


corresponding bits in the two vectors are equal.

If all the bits are equal, the result is 1 (true); otherwise, the result is 0 (false).

For scalar data types, the logical equality operator simply checks if the two values are equal.

Example:

module LogicalEqualityExample(input [3:0] A, input [3:0] B, output reg equal);

always @*

equal = (A == B); // Logical equality comparison

endmodule

In this example, the logical equality operator compares two 4-bit vectors A and B. If all
corresponding bits in A and B are equal, the output signal "equal" will be set to 1; otherwise,
it will be set to 0.

Bitwise Equality (===) Operator:

the bitwise equality operator performs a bit-by-bit comparison of the entire vectors, and the
result is 1 (true) only if all the bits in the vectors are equal.

Example:

module BitwiseEqualityExample(input [3:0] A, input [3:0] B, output reg equal);

always @*

equal = (A === B); // Bitwise equality comparison

endmodule

the bitwise equality operator compares two 4-bit vectors A and B. The output signal "equal"
will be set to 1 only if all bits in vector A are equal to the corresponding bits in vector B.

Que 14) What is the purpose of the wildcard character ("z" and "x") in case equality
operators?

The wildcard characters "z" and "x" in case equality operators (casez and casex) serve the
purpose of representing "don't care" conditions.

They allow you to define patterns that match multiple values or unknown values in the input
signal, making case equality constructs more flexible and suitable for handling uncertain or
unspecified conditions.

"z" Wildcard: The "z" wildcard character represents a high-impedance state (also known as
"unknown" or "floating") in Verilog
@shraddha_pawankar Date:27/07/23

It is typically used to indicate that the corresponding bit in the pattern can match any value,
including 0 or 1, as well as "z" itself

EX: module WildcardZExample(input [1:0] data_in, output reg [3:0] data_out);

always @*

casez(data_in)

2'b00z: data_out = 4'b0000; // Matches 0000 and 0001 (z acts as don't care)

2'b01z: data_out = 4'b0001; // Matches 0100 and 0101 (z acts as don't care)

default: data_out = 4'b1111; // Unhandled case, default output

endcase

endmodule

"x" wildcard character

The "x" wildcard character represents an unknown or unspecified value in Verilog.

It is used to indicate that the corresponding bit in the pattern is irrelevant or has an
undefined value. Like "z," "x" can match any value, including 0, 1, "z," or "x" itself.

EX: module WildcardXExample(input [1:0] data_in, output reg [3:0] data_out);

always @*

casex(data_in)

2'b00x: data_out = 4'b0000; // Matches 0000, 0001, 0010, 0011 (x acts as don't care)

2'b01x: data_out = 4'b0001; // Matches 0100, 0101, 0110, 0111 (x acts as don't care)

default: data_out = 4'b1111; // Unhandled case, default output

endcase

endmodule

Que 15) How do you handle "don't care" conditions in case equality when dealing with
asynchronous inputs?

Example:

module DFlipFlopAsyncReset(input clk, input rst_n, input D, output reg Q);

always @(posedge clk or negedge rst_n)

begin

if (!rst_n) // Asynchronous reset

Q <= 1'b0; // Reset the flip-flop to 0

else // Synchronous operation


@shraddha_pawankar Date:27/07/23

casez(D)

1'bx: Q <= Q; // Preserve previous state if D is unknown (don't care)

1'b0: Q <= 1'b0; // Set Q to 0 if D is 0

1'b1: Q <= 1'b1; // Set Q to 1 if D is 1

endcase

end

endmodule

Inside the case equality construct, we handle "don't care" conditions by using the "x"
wildcard.

If D is unknown (don't care), we preserve the previous state of Q.

This ensures that during uncertain input scenarios, the flip-flop will maintain its current state
until a valid input is provided.
PROCEDURAL BLOCK

In Procedural block

 LHS = reg type


 RHS = reg/wire

There are two types of procedural block

1) Always block
2) Initial block

INITIAL BLOCK

1) Initial block Is a procedural block


2) All the statements inside initial block is executed sequentially
3) Initial block executes only once ,starting time t=0;
4) It has one or more than initial block
5) All initial block executes concurrently in arbitrary order starting at simulation time.
6) Initial block is used to initialize the circuits variables and registers with specific value
at the start of simulation.
7) In initial block ,blocking assignments ( = ) are usually used to initialize variables and
registers with specific values at the start of simulation.
8) Initial block is not synthesizable for ASIC (synthesizable in some FPGA)
9) Multiple statements we can write begin-end block
10) Verilog also guarantee that the initial block starts before any always block

----------------------------------------------------------------------------------------------------------
ALWAYS BLOCK

1) Always block is a procedural block


2) All the statements inside always block is executed sequentially.
3) Always block executes continuously at t=0; based on triggering event
4) It has more than always block.
5) Always block is used to describe the behavior of the circuit during its operation.
6) The always block may have sensitivity list.
Sensitivity list changes in input signal that should cause the block to be executed.
7) In always block,non-blocking assignment are used to ensure correct behavior of
sequential logic and avoid race condition
Always @( inputs ) --- Combinational

 Combinational logic is a type of digital circuit whose output is purely function of


present state only
 Blocking assignment is used for combinational logic
 Reg variable is used only for L.H.S variable

Example :

module half_adder(a,b,sum,carry);

input a,b;

output reg sum,carry;

always@(a or b)

begin

sum = a+b;
carry= a&b;

end
endmodule

 always block includes all the input signals(user defined signal)


 always block depends on these signal
 if we don’t mention any signal in always block then it may generate false hardware or
simulation and synthesis mismatch.
--------------------------------------------------------------------------------------------------------------------------------------

always@(*)
 Here we have not included any signal in sensitivity list.
We are asking simulator to include sensitivity list for us.
 When always @(*) is helpful
When we have always block ,which depends on lots of input signal.Writing all these
signal are time consuming and if we miss any signal then it may generate false
hardware.
 It Is used for combinational logic
--------------------------------------------------------------------------------------------------------------------------------------

always@()
Without sensitivity list the always block repeats continuously throughout the simulation
without waiting for triggering event.
--------------------------------------------------------------------------------------------------------------------------------------
always@(posedge clk) ---------------- sequential logic
 sequential logic must use always@(posedge clk)
 else synthesis tool wont generate sequential logic in hardware.
 For sequential logic,we use non-blocking assignment
Example:

module dff(clk,rst,d,q);
input d,clk,rst;
output reg q;

always@(posedge clk)
begin

if(rst)
q<=0;

else

q<=d;
end

endmodule

Example:

always@(x,y, sel)
if(sel)

output <= x;

else

output <= y;

output:

It will generate latch

If we used non blocking assignment in combinational logic it will create latch

Example:

always@(posedge clk)

if(sel)
output <= x;

else
output <= y;
output:

it will generate flipflop

it we used non blocking assignment in sequential logic it will generate flipflop(correct hardware)

--------------------------------------------------------------------------------------------------------------------------------------
Blocking Assignment( = )
1) Blocking assignment is a one step process
2) Evaluate the RHS of the expression and update the LHS without any delay.
3) Blocking statement executed in the Active region of Verilog stratified event queue.
4) While modelling combinational logic,blocking statements are preffered .
5) Blocking statement can be used in initial,always blocks and assign statements.
6) blocking assignment executed sequentially.
7) Any delay attached is also got added to delay in execution of next statement.
8) It is time consuming simulation.
-----------------------------------------------------------------------------------------------------------------

Non Blocking Assignment ( <= )


1) Non-Blocking assignment is a two step process
2) Evaluate the RHS expression at the beginning of time step and update the LHS at the
end of time step.
3) Evaluation of Non blocking statement occurred in Active region and updation of Lhs
side happen in NBA region
4) While modelling sequential logic,non blocking statements are preffered.
5) Non blocking can only be used in initial and always block but assign statements can
not used.
6) Non-blocking assignment executed concurrently.
7) Do not cause delays in the execution of subsequent statement.They are more
efficient

Why should a non blocking assignment be used for sequential logic,and what
would happen if a blocking assignment were used.
 In Verilog,non-blocking assignment (<=) should be used for
sequential logic
 Non-blocking assignment follow concurrent execution of
multiple assignment within the same always block
 If a blocking assignment were used in a sequential block,it
causes race around condition.
 This can lead unpredictable behaviour and incorrect results
in the circuit.

Why should a blocking assignment be used for combinational logic,and what


would happen if a non-blocking assignment were used.

 Blocking assignment should be used for combinational logic


 Blocking assignment follow sequential execution.Therefore
there is no risk of race condition.
 Use of blocking assignment in combinational logic is preffered
because it avoids unneccesary complexity and confusion.
 If a non blocking assignments were used in combinational
logic,it would cause error but it would be unneccassary and
could potentially confuse other designers who are modifying
the code.
FUNCTION

SYNTAX : function <return type> <function name>

EX:1 Basic Example with arguments and direction


module tb;

function compare(input int a,b);

if(a>b)

$display("A is greater than B");

if(a<b)

$display("A is less than B");

if(a==b)

$display("A is equal to B");

endfunction

initial

begin

compare(10,5);

compare(10,10);

compare(3,4);

end

endmodule

# KERNEL: A is greater than B


# KERNEL: A is equal to B
# KERNEL: A is less than B

https://www.edaplayground.com/x/G7ie

Ex:2 Function argument in parathesis


module tb;

int x;

function int sum(input int a,b);


sum=a+b;

$display("a=%0d b=%0d sum=%0d",a,b,sum);

endfunction

initial

begin

x= sum(3,4);

end

endmodule

# KERNEL: a=3 b=4 sum=7

https://www.edaplayground.com/x/j7ex

EX:3 Function with return value with return keyword

If the function name is used outside the function, the name indicates the scope of the whole function.

module tb;

int x;

function int sum;

input int a,b;

return a+b;

endfunction

initial

begin

x= sum(10,5);

$display("x=%0d",x);

end

endmodule
# KERNEL: x=15

https://www.edaplayground.com/x/BFiB

Ex:4 Discarding function return value


SystemVerilog void data type is used to discard a function’s return value without any warning
message.

module tb;

function int sum;

input int a,b;

return a+b;

endfunction

initial

begin

$display("calling function");

void'(sum(2,3));

end

endmodule

# KERNEL: calling function

https://www.edaplayground.com/x/ZPzJ
-------------------------------------------------------------------------------------------------------------------------------------
SYSTEM TASKS

INTERNAL VARIABLE MONITORING SYSTEM TASKS


$display,$write,$strobe,$monitor

$display/$write
 Displaying the values of variables or strings or expression.
 $display/$write is used to display immediate value
 It is used in active region
 $display = inbuilt new line character
 $write = doesn’t have inbuilt new line character
 $display is used power analysis

Que 1) What is the purpose of the $display command in Verilog?

It is used for printing the message or variables

It also provides for debugging purpose

Que 2) Explain the syntax of $display and its basic format specifiers.

Syntax:

$display(“Format specifier”,arguments);

Que 3) What are the different format specifiers available in $display?

 %d: For displaying decimal (integer) values.


 %b: For displaying binary values.
 %h: For displaying hexadecimal values.
 %s: For displaying strings.
 %f: For displaying real (floating-point) values.
 %t: For displaying time values.

Que 4) What are the limitations of $display in Verilog simulations?

 It may impact simulation performance, especially when used extensively.


 It can be challenging to track long simulation logs with many $display
statements.
 It cannot be used for generating waveform files.
Que 5) Describe the significance of $time and $stime with $display.

$time and $stime is a system function that can be used with $display to display simulation
time.

$time = returns current simulation time

$stime = returns simulation time in real time

Que 6) Discuss the usage of $display for visualizing simulation waveforms.

$display is not for waveform viewer.

It just simply print the message.

We can visualize behaviour of signals

Que 7) How do you use $display to display multi-line messages?

Each $display statement generates new line in the console output

Que 8) How do you use $display to print system task names dynamically?

We can $sformat system task to dynamically create strings.

Que 9) Explain the role of $urandom and $urandom_range with $display for random
stimulus generation.

We can display random stimulus

$monitor: Monitor a signal when its value changes.


$monitoron = enables monitoring

$monitoroff = disables monitoring during simulation

Que 1) What is the purpose of the $monitor system task in Verilog?

Monitoring signal values during simulation

It is used for debugging and verification

Que 2) How do you use $monitor to monitor signal values during simulation?

We need to include always or initial block

Que 3) How can you use $monitor to monitor multi-dimensional arrays?

We can use nested loop

Que 4) How can you use $monitor to observe clock and reset signals?

Ex:

always@(posedge clk,posedge rst)


$monitor(“clk=%0b rst=%0b”,clk,rst);

Que 5) Can $monitor be used for real-time monitoring during simulation?

Yes, it continuously updates the values of monitored signal

Que 6) Discuss the usage of $monitor for debugging FSMs (Finite State Machines).

Continuously monitoring current state,state transition and input.

Que 7) Can you use $monitor for monitoring signals across different clock domains?

Yes, ensure to provide proper synchronization to avoid meatstability issues.

Que 8) Explain the usage of $monitor for power analysis and optimization in Verilog
designs.

Continuously observing toggling behaviour of critical signals during simulation

Que 9) How do you use $monitor for error checking and diagnostics during
simulations?

We can place $monitor in critical parts of code for error checking

Que 10) Can $monitor be used to debug dynamic changes in variable values?

Yes, $monitor can be used to debug dynamic changes in variable values by continuously
monitoring the variable and displaying its updated value whenever it changes.

Que 11) How can you use $monitor for transaction-level modeling in Verilog?

In transaction-level modeling, $monitor can be used to continuously monitor the values of


transaction variables and display transaction information during simulation. This aids in
debugging and analyzing the behavior of the design at a higher level of abstraction.

Que 12) How can you use $monitor to identify timing violations in Verilog designs?

By monitoring critical signals involved in timing paths, $monitor can be used to detect timing
violations during simulation. Engineers can track the signal values and identify potential
setup and hold violations.

Que 13) How does $monitor handle multiple simultaneous signal changes?

The console output will show the most recent values of the monitored signals.

Que14) Describe the application of $monitor in debugging race conditions in the


design.

$monitor is valuable for debugging race conditions in the design by continuously monitoring
signals involved in the potential race.

$strobe: it displays simulation data at the end of current simulation time.


$stop : suspends the simulation
$finish : Terminates the simulation

NOTE :
In Verilog, the behavior of $monitor and $display cannot be directly interchanged because
they are different system tasks with distinct functionalities.

While We cannot directly change the behavior of $monitor to that of $display or vice versa,
we can achieve similar functionalities using both system tasks in different scenarios:

1. If we want to get real-time updates of signal values continuously, use $monitor in an


always block.
2. If we want to display specific messages or signal values at particular points in the
code, use $display in initial or always blocks.

Remember that $monitor is more suitable for real-time debugging and monitoring, whereas
$display is better for selective or periodic printing of messages and signal values.
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
FUNCTIONS & TASK

VERILOG

 It allows to write reusable code


 Helpful in Testbench simulation
 Instead of writing of code again & again we can
call the function or task.This makes code cleaner
and easy to read
---------------------------------------------------------------------------------------------------------------------------
FUNCTION :Function must have at least one input argument.
TASK :Task may have zero arguments or more arguments of type
input,output or output
-------------------------------------------------------------------------------------------------------------------
FUNCTION :It doesn’t contain time delay,timing or timing control
statements
TASK :Tasks may include delay,timing or timing control statements.-
--------------------------------------------------------------------------------------------------------------------
FUNCTION :Non blocking assignment inside function are not
allowed.
TASK :Task can use blocking and non blocking assignments
----------------------------------------------------------------------------------------------------------------
FUNCTION :Always return a single value
TASK :Tasks doesn’t return any value.
----------------------------------------------------------------------------------------------------------------
FUNCTION :Always execute at 0 ns.
TASK :Task contains timing delay
-------------------------------------------------------------------------------------------------------------------
FUNCTION :No delay like posedge,negedge,delay,wait.So it is
purely combinational circuit
TASK :Task is for combinational and sequential circuit.
-------------------------------------------------------------------------------------------------------------------
FUNCTION :Function can enable other function but not another
tasks.
TASK :Task can call other task and function
--------------------------------------------------------------------------------------------------------------------------------------
FUNCTION :Function cannot be disabled using disable keyword
TASK: Task can be disabled using disable keyword
FUNCTION SYNTAX:
function <return_type> <function_name> (input <port_list>,inout
<port_list>, output <port_list>);
...
return <value or expression>
endfunction

TASK SYNTAX:
task <task_name> (input <port_list>, inout <port_list>, output
<port_list>);
...
endtask

Similarities between Task and Function


 Both are static in nature by default.
 Both support default arguments and arguments have input direction
by default unless it is specified.
 Multiple statements can be written without using a begin .. end block.
Zero simulation delay(#0)
1) We can delay the simulation by the smallest unit of time
2) #0 operator is used to verify a delay in simulation time.
3) #0 is used to indicating the smallest possible delay
4) By including #0 in the simulation block,the simulation will pause for
smallest time unit.
5) #0 is used to avoid race around condition
6) Provides proper synchronization between DUT and TB
7) Maintaining proper order in non blocking assignments
8) It is used in Inactive region.
------------------------------------------------------------------------------------------------

Why delays are not synthesiable?

1) If we are using synthesis tool


X= #10 y;
Synthesis tool simply ignore #
X=Y
2) In RTL, we write synthesis model. Mainly focus on
area,clock,frequency.
3) Delays are not realistic doesnt describe the real hardware.
4) If we add delay ,it consumes more than 70% silicon surface.
5) So the design cant be fitted.
--------------------------------------------------------------------------------------------

How this delay would be converted into real hardware?

o We can implement the delay by using counters and FSM


techniques.
FOR LOOP

The for loop iterates till the mentioned condition is satisfied.


Syntax:
for (<initialization>; <condition>; <update>) begin
...
End

Example:
module add ( clk,din,dout);

input clk;

input [3:0] din;

output reg [3:0] dout;

integer i;

always@(posedge clk)

begin

dout = 0;

for(i=0;i<5;i=i+1)

begin

dout = dout + din[i];

end

end

endmodule

Write a Verilog module that uses a for loop to implement a 4-bit up-counter. The counter
should start at 0 and count up to 15 (4'b1111). The counter should also include a reset
signal, and it should only count when the enable signal is high. Additionally, provide a
testbench to verify the functionality of the counter.

module counter(clk,rst,en,count);

input clk,rst,en;

output reg [3:0] count;

integer I;
always@(posedge clk)

begin

if(rst)

count <= 4'b0000;

else if(en==1)

begin

for(i=0;i<15;i=i+1)

count <= i;

end

end

endmodule

Que 1) How does the for loop differ from other loop constructs like the while
loop and the repeat loop in Verilog?

The for loop differs from other loop constructs in Verilog as follows:
 Unlike the while loop, the for loop requires explicit initialization,
condition, and increment statements.
 Unlike the repeat loop, the for loop allows you to specify a range of
iterations using the loop parameters.

Que 2) Can you use a for loop in synthesizable Verilog code? Why or why not?

 Yes, the for loop can be used in synthesizable Verilog code, provided that it
adheres to certain guidelines. The loop parameters, including the initialization,
condition, and increment, must be based on constant values.

Que 3) How do you control the execution of a for loop in Verilog? What are the
parameters you specify in the loop declaration?

 For loops are typically used in Verilog for synthesizable designs when you need
to perform a specific action a fixed number of times, such as iterating through
elements of an array or performing a sequence of operations repeatedly.

Que 4) What are the advantages of using a for loop over other loop constructs in
Verilog?

 The for loop allows you to specify the loop parameters directly in the loop
declaration, making the code easier to read and understand.

Que 5) What are the potential risks or issues to watch out for when using a for loop in
Verilog?
 When using a for loop in Verilog for synthesizable code, you should be cautious
to ensure that the loop parameters are based on constant values.
 Avoid using loop parameters that depend on signals or variables that can
change during runtime, as this can lead to unpredictable behavior in the
hardware.

Que 6) How can you optimize the performance of a for loop in Verilog for
synthesizable designs?

 To optimize the performance of a for loop in Verilog for synthesizable designs,


consider minimizing the number of iterations and the complexity of the
operations within the loop.

-------------------------------------------------------------------------------------------------
FOREACH LOOP

 The foreach loop in SystemVerilog iterates over the array element.


 Unlike for loop, foreach loop does not require initialization, condition, or
update value.
Syntax:
foreach (variable[iterator]) begin
...
end

Ex: foreach loop for 1-D array


module tb;

int array[3]='{1,2,3};

initial

begin

foreach(array[i])

$display("array[%0d]=%0d",i,array[i]);

end

endmodule

output:
# KERNEL: array[0]=1
# KERNEL: array[1]=2
# KERNEL: array[2]=3

https://www.edaplayground.com/x/Lwvc
--------------------------------------------------------------------------------------------------------------------------------------
Ex: Foreach loop for 2-D array
module tb;

int array[3][2]='{'{1,2},'{2,3},'{4,5}};

initial

begin

foreach(array[i,j])

$display("array[%0d][%0d]=%0d",i,j,array[i][j]);
end

endmodule

output:
# KERNEL: array[0][0]=1
# KERNEL: array[0][1]=2
# KERNEL: array[1][0]=2
# KERNEL: array[1][1]=3
# KERNEL: array[2][0]=4
# KERNEL: array[2][1]=5

https://www.edaplayground.com/x/YHGi
--------------------------------------------------------------------------------------------------------------------------------------
Ex: foreach loop for 3D array
module tb;

int array[3][3][3] = '{'{'{1,2,3},'{4,5,6},'{7,8,9}},

'{'{1,3,5},'{4,5,9},'{8,9,0}},

'{'{5,9,0},'{7,6,0},'{2,9,3}}};

initial

begin

foreach(array[i,j,k])

$display("array[%0d][%0d][%0d]=%0d",i,j,k,array[i][j][k]);

end

endmodule

output:
# KERNEL: array[0][0][0]=1
# KERNEL: array[0][0][1]=2
# KERNEL: array[0][0][2]=3
# KERNEL: array[0][1][0]=4
# KERNEL: array[0][1][1]=5
# KERNEL: array[0][1][2]=6
# KERNEL: array[0][2][0]=7
# KERNEL: array[0][2][1]=8
# KERNEL: array[0][2][2]=9
# KERNEL: array[1][0][0]=1
# KERNEL: array[1][0][1]=3
# KERNEL: array[1][0][2]=5
# KERNEL: array[1][1][0]=4
# KERNEL: array[1][1][1]=5
# KERNEL: array[1][1][2]=9
# KERNEL: array[1][2][0]=8
# KERNEL: array[1][2][1]=9
# KERNEL: array[1][2][2]=0
# KERNEL: array[2][0][0]=5
# KERNEL: array[2][0][1]=9
# KERNEL: array[2][0][2]=0
# KERNEL: array[2][1][0]=7
# KERNEL: array[2][1][1]=6
# KERNEL: array[2][1][2]=0
# KERNEL: array[2][2][0]=2
# KERNEL: array[2][2][1]=9
# KERNEL: array[2][2][2]=3

https://www.edaplayground.com/x/wRCY
--------------------------------------------------------------------------------------------------------------------------------------
FOREVER LOOP

 forever loop runs indefinitely. To terminate the loop, a ‘disable’ statement can be
used.
 Forever loop doesn’t contain any expression
 And executes forever times until $finish task encountered.
 Forever loop is equivalent to while(1)
Syntax:
forever

begin
-----
end

Example: Generate clock of 50% duty cycle


module tb;
reg clk;
initial
begin
clk=1'b0;
forever
begin
#30 clk = ~clk;
$finish();
end
end
endmodule

https://www.edaplayground.com/x/vqLi

Que 1) How can you ensure that a "forever loop" does not create an infinite simulation
in Verilog?

 Use $finish system task inside the "forever" loop.


Que 2) What are some potential risks or issues with using a "forever loop" in hardware
design?

 The main risk with a "forever loop" in hardware design is that it creates an
infinite loop that cannot be broken out of during actual hardware operation.
 This can lead to increased power consumption or undesired behavior if the
loop is not carefully designed.

------------------------------------------------------------------------------------------------------
Que 3) In a Verilog testbench, how might you use a "forever loop" to create a
continuous stimulus for the design under test?

 In a verilog testbench ,”forever loop” can be used to continuously apply


stimulus to the design under test.
 For eg input signal clk
 Clk <= ~clk; need to toggle the stimulus.

Que 4) When using a "forever loop" in a testbench, how do you ensure that the
testbench terminates appropriately after testing the desired functionality?

 In a testbench, you can use $finish or $stop system tasks to terminate the
simulation after a specific condition is met

Difference between always and forever loop

Always:

 Always is a module item


 Always is synthesized
 It executes its statements whenever there is a change in the signals
specified in its sensitivity list.
 The always block is commonly used to describe sequential logic,
state machines, and register transfer level (RTL) code.
Forever loop:

 Forever is a procedural statement so written inside always block


 Forever is not synthesized
 The forever block is used to create an infinite loop in Verilog.
 The forever block is often used in testbenches
------------------------------------------------------------------------------------------------------
--
REPEAT LOOP

Repeat loop:
Repeat loop is used to execute statements a given number of times.
The repeat loop is particularly useful when you want to perform a task
iteratively for a fixed number of iterations.
Syntax:
repeat(<number>)
begin
……..
end

Example :
module tb;
int array[4] = '{100,200,300,400};
int i;
initial
begin
repeat($size(array[i]))
begin
$display("array[%0d]=%0d",i,array[i]);
i++;
end
end
endmodule
output:
# KERNEL: array[0]=100
# KERNEL: array[1]=200
# KERNEL: array[2]=300
# KERNEL: array[3]=400

https://www.edaplayground.com/x/T6nc

Q.1) Can you use a repeat loop in synthesizable Verilog code? Why or why not?
 No, the repeat loop is not synthesizable in Verilog.
 Hardware description languages like Verilog are primarily used for describing
hardware structures and behavior, and synthesizable constructs must have a
fixed and known number of iterations.

Q.2) In what situations would you typically use a repeat loop in Verilog?

 The repeat loop is typically used in Verilog testbenches and simulation


environments for repetitive tasks, such as generating stimuli, checking output
responses, or monitoring specific behaviors for a fixed number of simulation
cycles.

Q.3) How do you control the execution of a repeat loop in Verilog? How many times
will the loop iterate?

 The execution of a repeat loop in Verilog is controlled by the iteration_count


specified in the repeat statement.

Q.4) What are the advantages of using a repeat loop over other loop constructs in
Verilog?

 The advantage of using a repeat loop over other loop constructs is its simplicity
for specifying a fixed number of iterations.

Q.5) What are the potential risks or pitfalls of using a repeat loop in Verilog
simulations?

 One potential risk of using a repeat loop in Verilog simulations is accidentally


specifying a large number of iterations, which could lead to simulations taking
longer to complete than intended. Care should be taken to set an appropriate
iteration_count to avoid excessive simulation time.

------------------------------------------------------------------------------------------------------
Q.6) How can you achieve the same functionality as a repeat loop in synthesizable
Verilog code?
 To achieve similar functionality as a repeat loop in synthesizable Verilog code,
you would typically use a for loop with an explicitly defined iteration count.

Q.7) What should you be cautious about when using a repeat loop to avoid
unintended consequences?
 When using a repeat loop, you should be cautious about setting the
iteration_count appropriately to avoid unnecessary simulation time.
 Additionally, since repeat loops are not synthesizable, we should avoid using
them in hardware description code meant for synthesis.

------------------------------------------------------------------------------------------------------
WHILE LOOP

While loop:

A while loop is a control flow statement that executes statements repeatedly if the
condition holds true else loop terminates.
Syntax:
While(<condition>)
Begin
//statement
End
---------------------------------------------------------------------------------------------------------------------
-
While loop is typically used in testbenches and other verification constructs rather than
in synthesizable hardware descriptions.
---------------------------------------------------------------------------------------------------------------------
---

Example: on While loop

module tb;
reg [3:0] count;
initial
begin

count=0;
while(count<10)
begin
$display("value of count=%0d",count);
count++;

#10;
end
$display("Count reach to value 10,Terminates the count");
end
endmodule
output:
KERNEL: count=0
# KERNEL: count=1
# KERNEL: count=2
# KERNEL: count=3
# KERNEL: count=4
# KERNEL: count=5
# KERNEL: count=6
# KERNEL: count=7
# KERNEL: count=8
# KERNEL: count=9
# KERNEL: count reaches to 10,Terminates the count

https://www.edaplayground.com/x/Xuie

Example: on do while loop


module tb;

reg [3:0] count;

initial

begin

count=0;

do

begin

$display("count=%0d",count);

count++;

end

while(count<10);

$display("count reaches to 10,Terminates the count");

end

endmodule

output:
KERNEL: count=0
# KERNEL: count=1
# KERNEL: count=2
# KERNEL: count=3
# KERNEL: count=4
# KERNEL: count=5
# KERNEL: count=6
# KERNEL: count=7
# KERNEL: count=8
# KERNEL: count=9
# KERNEL: count reaches to 10,Terminates the count

https://www.edaplayground.com/x/TaVZ

Example on while(1):

In verilog, the while(1) loop is common construct used for creating an infinite
loop.

module tb;

reg clk;

initial

begin

clk=0;

while(1)

begin

#5

clk=~clk;

$display("value of clk=%0b",clk);

end

endmodule

output:
Result reached the maximum of 5000 lines. Killing process.(infinite times)
Que1 ) In what situation would you use typically use a while loop in verilog?

 While loops are typically used in verilog testbenches and simulation


environment.
 While loop is used for generation of clk signals,monitoring specific
behaviour.

Que2) How do you control the execution of a while loop in verilog? What
condition should be met to terminate the loop?

 We can control the execution by specifying condition in while loop.


 Ioop will continuously executing as long as the condition remains
true.terminates when condition is false

Que 3) Is a while loop is suitable for generating a continuous clock signal in


hardware design?

 No while loop is not suitable for generating continuous clock in


hardware design.
 Hardware clock generation achieved using dedicated clock
generation circuits,clock divider.

Que 4) If you need to create a counter that counts from 0 to 15 in Verilog,


would you use a while loop or a for loop? Why?
 For a counter that counts from 0 to 15, a for loop is typically
preferred in Verilog. The for loop allows you to specify the
start, end, and increment conditions directly in the loop
declaration, making it more suitable for counting operations .

Que 5) What are the potential risks of using a while loop in simulation or
testbench environments?
 One potential risk of using a while loop in a simulation or
testbench is the possibility of causing an infinite loop if the
termination condition is not correctly set.
 This can lead to simulations hanging ..
------------------------------------------------------------------------------------
-
@shraddha_pawankar Date:25/07/23

@shraddha_pawankar

1) Compiler directive is a special instruction that provides instruction to the verilog


compiler.
2) It provides additional information to the compiler.
3) Verilog provide compiler directive. All compiler directive are defined using ` keyword.

`include Compiler directive:


 Used to insert the entire contents of a source file in another file during
compilation.
 It allows us to spilt our code into multiple file for better organization and
reusability.
 Syntax:
`include "filename.v"

`define Compiler directive:


 It creates a macro for substitution
 Can be used inside and outside module definition
 Syntax:
`define MACRO_NAME value

`timescale Compiler directive:


 It specifies time unit and time precision of the modules.
 It defines the time units used in delays and other time-related
constructs.
 Syntax:
`timescale time_unit / time_precision

Que 1) How do you define a macro using the define directive with
parameters?
Ex:
`define dt_width 8
`define ad_depth 256
Que 2) How can you handle multiple define statements with the same
macro name?
@shraddha_pawankar Date:25/07/23

define statement with the same macro name takes precedence.


Que 3) Is it possible to redefine a macro using the define directive?
Yes it is possible
Que 4) What happens if you omit the timescale directive in a Verilog file?
Default timescale is used for simulation
Que 5) Can you use the timescale directive with different units and
precision in different files?
Yes it is possible.each file can use different different timescale.
Que 6) How do you specify the precision and units in the timescale
directive?
It is separated by /
Ex:
`timescale time_unit/time_precision
Que 7) What are the advantages of using compiler directives in Verilog?
It is a way to control compilation process
It improves reusability
We can customize the design parameter

Que 8) Can compiler directives be used in both Verilog and SystemVerilog


files?
Yes we can used
Que 9) What is the significance of the order of compiler directives in a Verilog
file?
The order of compiler directives in a Verilog file does not generally affect their
behavior.
However, it is good practice to place them at the beginning of the file for
better readability and consistency.
Que 10) How do you enable or disable specific functionality using
compiler directives?
We can enable or disable specific functionality using compiler directives by
defining or undefining macros.
Based on the defined macros, specific code blocks can be included or
excluded during compilation.
Que 11) How do you debug issues related to compiler directives in
Verilog?
we can print out the macro values using $display or $write statements
during simulation to ensure they are set correctly.
Que 12) Can you use compiler directives within a module or task
definition?
@shraddha_pawankar Date:25/07/23

No, compiler directives cannot be used within a module or task definition.


They must be placed outside any procedural blocks or module definitions.
Que 13) How do you pass a macro value to a sub-module instantiated
within a define macro?
We cannot directly pass a macro value to a sub-module instantiated within a
define macro.
Macros are simple text substitutions and do not support dynamic values.
To parameterize sub-module instances, we may need to use Verilog's
generate blocks or SystemVerilog's generate constructs.
Que 14) What are some best practices for using compiler directives in
large Verilog projects?
Code readability
Code maintainability
Provides some flexibility.
Que 15) How do compiler directives impact the synthesis process?
Compiler directives have no direct impact on the synthesis process. Synthesis
tools typically ignore compiler directives
Que 16) Is it possible to use the include directive recursively in Verilog
files?
Yes, the include directive can be used recursively in Verilog files, meaning that
an included file can itself contain another include directive to include
additional files.

Que 17) Can you use compiler directives to customize the testbench behavior
during simulation?

Yes, we can use compiler directives to customize the testbench behavior during
simulation. For instance,

we can use macros to enable or disable specific test cases or to switch between
different testing configurations.

Que 18) Can you use the timescale directive to specify units other than time in
Verilog?

No, the timescale directive is specifically used to specify time units and precision in
Verilog. It cannot be used to specify units other than time.

Que 19) How do you ensure consistent timescale settings across all Verilog files
in a project?

To ensure consistent timescale settings across all Verilog files, you can create a
common header file that includes the timescale directive with the desired settings.
@shraddha_pawankar Date:25/07/23

Then, include this header file in all other Verilog files.

Que 20) Is it possible to change the timescale setting during simulation, or is it


fixed once specified?

The timescale setting is fixed once specified at the beginning of the Verilog file and
remains constant throughout the simulation.

It cannot be changed during simulation runtime.

Que 21) How would you set up a timescale directive to have a time unit of 1ns and a
time precision of 100ps?

`timescale 1ns/100ps
@shraddha_pawankar Date:6/8/23

Structure
typedef struct{
reg [3:0] a;
reg [3:0] b;
} add_struct;

module tb;

add_struct a1; //handle

initial begin
a1.a=12;
a1.b=3;
$display("Value of addition : %0d",a1.a+a1.b);

end
endmodule

OUTPUT : # KERNEL: Value of addition : 15

https://edaplayground.com/x/bSkc
---------------------------------------------------------------------------
// Method is written by user in structure

//basically restrict each user should have clear understanding of a


method this is the first restriction of Reusability

// structure have a datamember but do not have chance to mention


methods

// class provides facility for data memebers and methods to access


single object

// when we create instance for a structure ,it will allocate a memory


@shraddha_pawankar Date:6/8/23

// handling method is very difficult in structure

// when we create instance for structure it immediately become usable

CLASS
class add;
reg [3:0] a;
reg [3:0] b;
reg [4:0] result;

task add_two(); //class has an ability to add methods


result=a+b;
endtask
endclass

module tb;
add a1; //class handle
reg[4:0] r;

initial begin
a1=new(); //when we add new method then it will allocate memory space
//then the required compution is performed
a1.a=12;
a1.b=3;
a1.add_two();
r=a1.result;
$display("value of addition : %0d ",r);
end
endmodule

# KERNEL: value of addition : 15

https://edaplayground.com/x/hw7F

Structure allow us collection of data(different datatype)


Class also allows us to collection of different data members with
methods
@shraddha_pawankar Date:6/8/23

For a structure if we create instance inside testbench, immediately start


using structure
For a class this is not the case,we need to create handle,add constructor
(new method) then only data member and methods are accessible
 1)In structure,reusability is not possible
 2) In class ,reusability is possible,we can extend the class

Understanding Extended class


class add;

reg [3:0] a;
reg [3:0] b;

reg [4:0] result;

function new(input reg[3:0] a,input reg[3:0] b);


this.a=a;
this.b=b;

endfunction

task add_two();
result=a+b;
endtask

endclass

class twice extends add;

function new(input reg[3:0] a); //overriding the base class constructor

super.new(a,a);
endfunction

endclass
@shraddha_pawankar Date:6/8/23

module tb;

twice t1;

initial begin
t1=new(12);
t1.add_two();

$display("value of addition=%0d",t1.result);
end
endmodule

OUTPUT : # KERNEL: value of addition=24

https://edaplayground.com/x/jYSQ

Note :
We get access to the data members as well as the method inside the parent class by using
extend keyword inside the derived class
And the entire process is referred to as inheritance

SUPER.NEW()

To initialize of all the data members of the parent class as well as


allocating memory for the derived class
@shraddha_pawankar Date:3/8/23

Que 1) Generate 16MHz and 8MHz clock


Calculation

// Generate f=16MHz clk

T=1/f

T=62.5ns

T/2=31.25ns

// Generate 8MHz clk

f=8MHz

T=1/f

T=125ns

T/2=62.95ns

Code:

`timescale 1ns/1ps

module tb;

reg clk_16=0;

reg clk_8=0;

always #31.25 clk_16 = ~clk_16;

always #62.5 clk_8 = ~clk_8;


@shraddha_pawankar Date:3/8/23

initial begin

$dumpfile("dump.vcd");

$dumpvars();

end

initial begin

#200

$finish();

end

endmodule

https://edaplayground.com/x/GWd6

Que 2) Write a code to generate a 9MHz square waveform for the signals
Timescale = 1ns and 3 digit precision

Calculation:

f=9MHz

T=1/f

T=111.11ns

T/2=55.55nsec

Code:

`timescale 1ns/1ps
module tb;

reg clk_9=0;

always #55.55 clk_9=~clk_9;


@shraddha_pawankar Date:3/8/23

initial begin
$dumpfile("dump.vcd");
$dumpvars();

end
initial begin
#200
$finish();
end

endmodule

https://edaplayground.com/x/LMAE

Que 3) Generate 640KHz clock in Verilog


`timescale 1ns/1ps

module tb;

reg clk;

always #781.25 clk=~clk;

initial
begin

clk=0;
end

initial
begin

$dumpfile("dump.vcd");
$dumpvars();
end
@shraddha_pawankar Date:3/8/23

endmodule
https://www.edaplayground.com/x/ZJrV

--------------------------------------------------------------------------------------------------------------------------------------
-
CODE CONVERTERS
A code converter circuit will convert coded information in one form to a
different coding form.

Binary to Gray Code Converter

module binary_to_gray(B,G);

input [3:0] B;

output [3:0] G;

assign G[3] = B[3];

assign G[2] = B[3]^B[2];

assign G[1] = B[2]^B[1];

assign G[0] = B[1]^B[0];

endmodule

https://www.edaplayground.com/x/MKhi
Gray to Binary Code Converter

module gray_to_binary(G,B);

input [3:0] G;

output [3:0] B;

assign B[3] = G[3];

assign B[2] = B[3]^G[2];

assign B[1] = B[2]^G[1];

assign B[0] = B[1]^G[0];

endmodule

https://www.edaplayground.com/x/Znh3
Binary to 2’s Complement Code Converter

module bin_complement_2s(in,out);

input [3:0] in;

output unsigned [3:0] out;

wire [3:0] temp;

assign temp = 4'b1111-in;

assign out = temp+4'b0001;

endmodule

https://www.edaplayground.com/x/KDfc
BCD to EXCESS-3 CODE Converter

module bcd_excess3(B,Ex_3);

input logic [3:0] B;

output logic [3:0] Ex_3;

always@(*)

begin

case(B)

4'b0000 : Ex_3 = 4'b0011;

4'b0001 : Ex_3 = 4'b0100;

4'b0010 : Ex_3 = 4'b0101;

4'b0011 : Ex_3 = 4'b0110;

4'b0100 : Ex_3 = 4'b0111;

4'b0101 : Ex_3 = 4'b1000;

4'b0110 : Ex_3 = 4'b1001;

4'b0111 : Ex_3 = 4'b1010;

4'b1000 : Ex_3 = 4'b1011;

4'b1001 : Ex_3 = 4'b1100;

default : Ex_3 = 4'bxxxx;

endcase

end

endmodule

https://www.edaplayground.com/x/Ts8n
FLIP FLOPS
 A flip-flop is the basic memory element for storing a bit
of information.

 It is an edge-triggered device.

 That is, it reacts to the edge of a pulse.

 A simple flip-flop has two stable states.

 Flopflops are preffered over latches,because they are


synchronous,more stable,easier to design and more
flexible.

D FLIP FLOP
 D flip flop is one of the most widely used flopflop in digital circuits.
 It is reliable.
 Less immune to noise.
 D flipflop can be easily cascaded in series to form more complex
circuit,such as counters and shift registers.
TRUTH TABLE

D Qn+1
0 0
1 1

Code(SYSTEM VERILOG)

module d_ff(clk,rst,d,q);
input logic clk,rst,d;
output logic q;

always_ff@(posedge clk)
begin
if(rst)
q<=1'b0;
else
q<=d;
end
endmodule
https://edaplayground.com/x/SbR5

T FLIP FLOP

 A T flip flop is known as a toggle flip flop because of its toggling


operation. It is a modified form of the JK flip flop.
 A T flip flop is constructed by connecting J and K inputs, creating a
single input called T.
 Hence why a T flip flop is also known as a single input JK flip flop.
TRUTH TABLE

T Qn+1
0 Qn
1 ~Qn
Code:
module t_ff(clk,rst,t,q);

input logic rst,clk,t;

output logic q;

always_ff@(posedge clk)

begin

if(rst)

q <=1'b0;

else

begin

if(t==1)

q <= ~q;

else

q <= q;

end

end

endmodule
https://edaplayground.com/x/C5U6

S R FLIP FLOP
 The SR flip flop is a 1-bit memory bistable device having two inputs, i.e., SET and
RESET.
 The SET input 'S' set the device or produce the output 1, and the RESET input 'R' reset
the device or produce the output 0.
 The SET and RESET inputs are labeled as S and R, respectively..
TRUTH TABLE

0 0 Qn
0 1 0
1 0 1
1 1 X
Code:
module sr_ff(clk,rst,s,r,q);

input logic s,r,clk,rst;

output logic q;

always_ff@(posedge clk)

begin

if(rst)

q <= 1'b0;

else

begin

case({s,r})

2'b00 : q<=q;

2'b01 : q <=0;

2'b10 : q <=1;

2'b11 : q <=1'bx;
endcase

end

end

endmodule

https://www.edaplayground.com/x/rw4Y
J K FLIP FLOP
JK Flip flop is an improved version of SR flip flop where the undefined
state of SR Flip flop is eliminated by providing feedback.
TRUTH TABLE

0 0 Qn
0 1 0
1 0 1
1 1 ~Qn

Code
module jk_flipflop(j,k,clk,rst,q);

input logic clk,rst,j,k;

output logic q;

always_ff@(posedge clk)

begin

if(!rst)

q<=1'b0;

else

begin

case({j,k})

2'b00 : q<=q;

2'b01 : q<=0;

2'b10 : q<=1;

2'b11 : q<=~q;

endcase
end

end

endmodule

https://www.edaplayground.com/x/XZaR

d LATCH using 2:1 MUX

module mux(a,b,s,y);

input a,b,s;

output reg y;

always @(a,b,s)

begin

y=(~s & a)|(s & b);

end

endmodule

module d_latch(d,q,en);

input d,en;

inout q;

mux mux_1(.a(q),.b(d),.s(en),.y(q));

endmodule

https://www.edaplayground.com/x/RjB4
@shraddha_pawankar Date: 1/8/2023

Divide by 2 clock using FSM

S0
00 S1
Clk_2=1 Clk_2=0

// Divide by 2 clock using FSM//

module clk_divide_2(clk,rst,clk_2);

input clk,rst;
output reg clk_2;

parameter s0=0,s1=1;

reg p_state,n_state;
//-------------Memory block--------------//

always@(posedge clk)
if(!rst)
p_state <= s0;
else
p_state <= n_state;
//--------Next state block-------------------//
@shraddha_pawankar Date: 1/8/2023

always@(p_state)
case(p_state)
s0 : n_state = s1;
s1 : n_state = s0;
default : n_state = s0;
endcase
//--------output block-------------------//
always@(p_state)
case(p_state)
s0 : clk_2=1;
s1 : clk_2=0;
default : clk_2 = 0;
endcase
endmodule

https://www.edaplayground.com/x/tGD5

33% duty cycle using FSM


@shraddha_pawankar Date: 1/8/2023

S0
S1
Clk_out =1
Clk_out=0

S2

Clk_out=0

Program:

module clk_33_duty_cycle(clk,rst,clk_out);

input clk,rst;
output reg clk_out;
reg[1:0] p_state,n_state;
parameter s0=2'b00,s1=2'b01,s2=2'b10;

//--------------Memory block-------------//

always@(posedge clk)
begin
@shraddha_pawankar Date: 1/8/2023

if(!rst)
p_state <= s0;
else

p_state<= n_state;
end
//---------Next state block-----------//

always@(p_state)

begin
case(p_state)
s0: n_state = s1;
s1: n_state = s2;
s2: n_state = s0;

default: n_state = s0;


endcase
end

//-------output block-------------//

always@(p_state)
begin
case(p_state)
s0 : clk_out=1;
s1 : clk_out=0;

s2 : clk_out=0;
default : clk_out=0;
endcase
end
endmodule

https://www.edaplayground.com/x/uLkr
@shraddha_pawankar Date: 1/8/2023

DIVIDE BY 3 CLOCK USING FSM

S0
Clk_1 = 1 S1
clk_2=1 Clk_1 = 0
clk_2=0

S2

Clk_1 = 0
clk_2=0

//Divide by 3 clock using FSM//


module clk_divide_3(clk,rst,clk_3);
input clk,rst;
output reg clk_3;
reg[1:0] p_state_1,n_state_1,p_state_2,n_state_2;

reg clk_1,clk_2;
parameter s0=2'b00,s1=2'b01,s2=2'b10;
@shraddha_pawankar Date: 1/8/2023

//------Memory block for clk_1---------//

always@(posedge clk)

begin
if(!rst)
p_state_1 <= s0;
else
p_state_1 <= n_state_1;

end
//--------define next state block for clk_1--------//

always@(p_state_1)
begin

case(p_state_1)
s0 : n_state_1 = s1;
s1 : n_state_1 = s2;
s2 : n_state_1 = s0;
default : n_state_1 = s0;

endcase
end
//------output block for clk_1------------//

always@(p_state_1)

begin
case(p_state_1)
s0 : clk_1 = 1;
s1 : clk_1 = 0;
s2 : clk_1 = 0;
default: clk_1 = 0;
@shraddha_pawankar Date: 1/8/2023

endcase
end
//------Memory block for clk_2---------//

always@(posedge clk)
begin
if(!rst)
p_state_2 <= s0;
else

p_state_2 <= n_state_2;


end
//---------Next state block clk_2--------//
always@(p_state_2)
begin

case(p_state_2)
s0 : n_state_2 = s1;
s1 : n_state_2 = s2;
s2 : n_state_2 = s0;
default : n_state_2 = s0;

endcase
end
//------output block for clk_2------------//
always@(p_state_2)
begin

case(p_state_2)
s0 : clk_2 = 1;
s1 : clk_2 = 0;
s2 : clk_2 = 0;
default : clk_2=0;
endcase
@shraddha_pawankar Date: 1/8/2023

// combining clk_1 and clk_2


assign clk_3 = clk_1 | clk_2;

end
endmodule

https://www.edaplayground.com/x/rgxM
@shraddha_pawankar Date:31/07/23

CLOCK_EDGE DETECTOR

 The Clock Edge Detector is a crucial component in digital systems that detects different
types of edges in a clock signal.

 It employs various operations to identify rising and falling edges.

 For the detection of a rising edge, the Clock Edge Detector performs an AND operation
between the clock signal and the complement of a delayed clock signal.

posedge_detect = clk & ~d_clk;

 On the other hand, to detect a falling edge, the Clock Edge Detector utilizes a similar
mechanism. It performs an AND operation between the complemented clock signal
and the delayed clock

negedge_detect = ~clk & d_clk;

Program:

module clock_edge(clk,d_clk,posedge_detect,negedge_detect);

input logic clk,d_clk;


output logic posedge_detect,negedge_detect;

assign posedge_detect = clk & (~d_clk);


assign negedge_detect = (~clk) & d_clk;
endmodule

https://edaplayground.com/x/HcXt

--------------------------------------------------------------------------------------------------------------------------------------

CLOCK BUFFER

 It creates copy of reference clock

 It is an Jitter Attenuator

 It removes noise from a reference clock

 assign clk_out = clk_in;

 Program

module clock_buffer(clk_in,clk_out);
input clk_in;
@shraddha_pawankar Date:31/07/23

output clk_out;

assign clk_out = clk_in;


endmodule

https://www.edaplayground.com/x/CKbM
@shraddha_pawankar Date : 29/07/2023

1) Code coverage is a metric or calculation automatically done by EDA tool


2) We do measurement on RTL code/Quality of Testbench.
3) Code coverage make sure that each piece of code covered.
4) Code coverage is done by the design enginner.
5) Design engineer submit code coverage report in verification team.
6) Tool dependant.
7) It is usually expressed in %
8) If code coverage is 100% it doesn’t mean 100% bug free.
9) Missing code coverage,holes in the test.
10) Code coverage is generated from RTL source code.

TYPES OF CODE COVERAGE


1. STATEMENT COVERAGE
2. BRANCH COVERAGE
3. CONDITION COVERAGE
4. EXPRESSION COVERAGE
5. TOGGLE COVERAGE
6. FSM COVERAGE
A) STATEMENT COVERAGE

Statement coverage covers all statement like blocking,non blocking and


continuous assignment.
The calculation for statement coverage is the count of statements during
simulations.
% statement coverage = Hits/Bins *100
Ex:
module mux_2to1(input wire a, b, sel, output reg y);
always @*
if (sel)
y = b;
else
y = a;
endmodule

count the total number of statements in the MUX module:


@shraddha_pawankar Date : 29/07/2023

One for the always block.


Two for the if-else statement.
Total no. of statement is 3.
During simulation, let's say both test cases were executed.
In the first test case, when sel is 0, the else part of the if-else statement is
executed,
and in the second test case, when sel is 1, the if part of the if-else statement is
executed.

Statement Coverage (%) =Hits/Bins *100


= 3/3*100
=100%

In practice, achieving 100% statement coverage may not always be possible,


especially in complex designs, but the goal is to get as close as possible to cover all
critical statements for thorough testing.

B) BRANCH COVERAGE
Branch coverage is a metric that covers branches like if-else,case,ternary operator
during simulation.
If branch:
It includes true branch and false branches.
If else part is missing,all false branch is added.
Case branch:
It includes case items as branches.

Branch Coverage (%) =Hits/Bins *100

Ex:
module mux_2to1(input wire a, b, sel, output reg y);
always @*
if (sel)
y = b;
else
y = a;
endmodule

The if-else statement has two branches: one for the if part (when sel is 1) and
another for the else part (when sel is 0).

During simulation, let's say both test cases were executed. In the first test case, when
sel is 0, the else part of the if-else statement is executed. In the second test case,
when sel is 1, the if part of the if-else statement is executed.
@shraddha_pawankar Date : 29/07/2023

Branch Coverage (%) =Hits/Bins *100

Branch Coverage (%) = (2 / 2) * 100


Branch Coverage (%) = 100%

C) Condition coverage:

Condition coverage is a metric that covers logical expression used in conditional


branches.

Ex:
module mux_2to1_enable(input wire a, b, sel, enable, output reg y);
always @*
if (enable)
y = (sel) ? b : a;
else
y = 0;
endmodule

The conditions are (enable) and (sel) .

During simulation, let's say all test cases were executed:

1. Test case 1: enable = 1, sel = 0


2. Test case 2: enable = 1, sel = 1
3. Test case 3: enable = 0

Condition Coverage (%) =Hits/Bins *100

Condition Coverage (%) = (2 / 2) * 100


Condition Coverage (%) = 100%

D) Expression coverage

The metric for expression coverage is the count of activity of expression on the RHS
of assignment statement.

Expression not supported for vectors.


@shraddha_pawankar Date : 29/07/2023

Expression Coverage (%) =Hits/Bins *100

EX:
module adder_4bit(input [3:0] a, b, input carry_in, output [3:0] sum, output carry_out);
assign {carry_out, sum} = a + b + carry_in;
endmodule

The Boolean expression is {carry_out, sum} = a + b + carry_in.


In this case, there is one unique Boolean expression.

In both test cases, the Boolean expression {carry_out, sum} = a + b + carry_in is


exercised.

Expression Coverage (%) =Hits/Bins *100


Expression Coverage (%) = (1 / 1) * 100
Expression Coverage (%) = 100%

E) TOGGLE COVERAGE
Toggle coverage is the ability to count and collect changes of state on specified
nodes.
Toggle coverage is a code coverage metric used in Verilog simulations to measure
the number of times each signal (bit) in the design toggles between 0 and 1 during
the simulation.

It helps identify signals that are not changing their values

Standard toggle: 0,1


Extended toggle : 0,1,Z (Covers 3 state)

Toggle Coverage (%) =Hits/Bins *100


F) FSM COVERAGE

FSM state : It counts if each state is covered at least once.

FSM Transition: it counts if all possible transition are covered including transition to
idle.

Que 1) How can code coverage be useful in identifying dead code and
unreachable statements?

Code coverage can be highly beneficial in identifying dead code and unreachable
statements
@shraddha_pawankar Date : 29/07/2023

Dead code refers to code that will never be executed during the runtime of the
program,
and unreachable statements are code segments that cannot be reached by any
sequence of inputs or conditions.

Here's how code coverage can help in identifying dead code and unreachable
statements
Statement Coverage
Branch Coverage
Function and Path Coverage
Que 2) What role does code coverage play in verifying Verilog designs with
complex state transitions?
Code coverage plays a crucial role in verifying Verilog designs with complex state
transitions.
In digital designs, state machines are often used to represent complex systems with
multiple states and state transitions

code coverage helps in verifying Verilog designs with complex state transitions:
State Coverage
Transition Coverage
Branch Coverage
Que 3) Explain the importance of directed testing and random testing in
achieving code coverage goals in Verilog.

By combining directed testing and random testing, verification teams can achieve
comprehensive code coverage and improve the overall quality of the Verilog design.

Directed testing ensures that specific functionalities and critical parts of the design
are well-tested,
while random testing explores unpredictable scenarios and uncovers hidden bugs
and edge cases.
The two approaches complement each other, making the verification process more
efficient and effective in identifying potential design issues.

Que 4) How can you use functional coverage and code coverage together to
enhance verification effectiveness?

By combining functional coverage and code coverage, you achieve a more holistic
approach to verification,

ensuring that the design is thoroughly tested at both high-level functionalities and
detailed code structures.
@shraddha_pawankar Date : 29/07/2023

This collaboration enhances verification effectiveness, increases confidence in the


correctness of the Verilog design, and leads to a more robust and reliable product.

Que 5) What are the best practices for achieving high code coverage in Verilog
testbenches?
Use Both Directed and Random Testing
Leverage Functional Coverage
Implement Assertions
Monitor Coverage Progress
Design Corner Cases
Use Code Coverage Tools
Use Constraints in Random Testing
Que 6) What is the significance of code coverage in verifying Verilog designs
with complex memory structures?
Code coverage plays a critical role in verifying Verilog designs with complex memory
structures.
Memory structures, such as RAMs, ROMs, FIFOs, and caches, are fundamental
components of many digital designs.
Verifying these complex memory structures can be challenging due to their size,
various read and write scenarios, and possible corner cases.

Identifying Uninitialized Memory


Testing Read and Write Scenarios
Coverage of Different Address and Data Combinations
Validating Timing and Synchronization

)
Difference between Verilog and
SystemVerilog (in terms of Verification):

Verilog System Verilog


In case of SV it is divided into 17
The event queue in verilog is regions including PLI and Re-
divided into 4 regions which are active,Re-inactive and Re-NBA
active,inactive,NBA and regions apart from the region
postponed region mentioned above which separate
the execution of events between
DUT and the Testbench.
Program block is absent in SV introduces program block to
verilog. provide race free interaction
We need to use DUT at posedge between DUT and TB.
of clock and drive the events of
TB at the negedge of clock to
take care of race around
condition.
SV introduces Clocking block to
provide proper synchronization
Clocking block is absent in verilog and race free condition.
clocking block in interface is used
as it provides input and output
skew to sample and drive

No Modports is used to define In SV, to define the direction of


the direction of interface signals signals
We used MODPORT.
Verilog uses module which is SV uses Class based Testbench
static level TB which is dynamic in nature.
Memory and arrays declaration SV uses packed/unpacked
on verilog are static in nature associative and dynamic array
which are dynamic in nature.
In verilog,there is no OOPS SV is class based Testbench it
features because it is static. supports OOPS features.
Provide reusability of code.
The randomization of stimulus in In SV scope of randomization
verilog is very limited. using CRCDV.
CRCDV-Constrained Random
Coverage Driven Verification.
In verilog Assertion feature is In SV,is provided with the
absent. powerful feature of assertion
which increase the observability
of a block to check whether any
bug is there by providing
intermediate check points

Task declaration in verilog is Task declaration in SV are


static in nature automatic in nature
Implementation of basic gates using 2:1 mux

module mux2_1(
input [1:0] i,
input sel,
output y);
assign y = sel ? i[1] : i[0];
endmodule

module gate(a,b,and_out,or_out,not_out);
input a,b;
output and_out,or_out,not_out;

mux2_1 m1 ({b,1'b0},a,and_out);

mux2_1 m2 ({1'b1,b},a,or_out);

mux2_1 m3 ({1'b0,1'b1},a,not_out);
endmodule

https://edaplayground.com/x/Tw8s
Implementation of Universal gates using 2:1 mux

module mux2_1(i,sel,y);
input [1:0] i;
input sel;
output y;

assign y = sel ? i[1]:i[0];


endmodule

module universal_gates(a,b, nand_out,nor_out);


input a,b;
output nand_out,nor_out;

wire b_bar;
mux2_1 m1 ({1'b0,1'b1},b,b_bar);
mux2_1 m2 ({b_bar,1'b1},a,nand_out);
mux2_1 m3 ({1'b0,b_bar},a,nor_out);
endmodule

https://edaplayground.com/x/b_LK
Special gates using mux

module mux2_1 (i,sel,y);


input [1:0] i;
input sel;
output y;

assign y = sel ? i[1]:i[0];


endmodule

module special_gates(a,b,xor_out,xnor_out);
input a,b;
output xor_out,xnor_out;

wire b_bar;

mux2_1 m1 ({1'b0,1'b1},b,b_bar);
mux2_1 m2 ({b_bar,b},a,xor_out);
mux2_1 m3 ({b,b_bar},a,xnor_out);

endmodule

https://edaplayground.com/x/AAWZ
Design half adder using MUX

module mux2_1(i,sel,y);
input [1:0] i;
input sel;
output y;

assign y = sel? i[1]:i[0];


endmodule

module half_adder(a,b,sum,carry);
input a,b;
output sum,carry;
wire b_bar;

mux2_1 m1 ({1'b0,1'b1},b,b_bar);

mux2_1 m2 ({b_bar,b},a,sum);

mux2_1 m3 ({b,1'b0},a,carry);

endmodule

https://edaplayground.com/x/kmjF
Implementation of 4:1 mux using 2:1 mux

module mux2_1(i0,i1,sel,y);
input sel;
input i0,i1;
output y;
assign y = sel ? i1 :i0;
endmodule

module mux4_1(i0,i1,i2,i3,sel1,sel0,y);
input i0,i1,i2,i3;
input sel1,sel0;
output reg y;
wire y1,y2;

mux2_1 m1 (sel0,i0,i1,y1);
mux2_1 m2 (sel0,i2,i3,y2);
mux2_1 m3 (sel1,y1,y2,y);
endmodule
Verification Plan for the MOD 12
Loadable UP/DOWN Counter
MOD 10 Loadable up/down counter:

Rst->

Clk->

Load-> MOD-12 -> [3:0] Dataout

Mode [Up/Down]->

[3:0] Datain->

An active high-loadable up/down counter is a digital circuit programmed to count up or down based
on user input. The counter can be loaded with an initial value, which sets the starting point for
counting.
When counting up, the counter increments by one on each clock cycle, and when counting down, the
counter decrements by one on each clock cycle. The direction of counting is determined by a control
signal, which can be set to either "up" or "down" mode.
Features:
• Reset
• Mode

❖ UP: Increment by one on each clock cycle.

❖ DOWN: Decrement by one on each clock cycle.

• Load
• Datain

❖ When Load is high, Counter can be loaded with the initial value dat in, which sets the
starting point for counting.
• Dataout

Strategies:
• Reset

❖ Reset should be distributed such that low value should occur number of times than high.

❖ Reference Model: if reset is “1” then output variable made equal to “0”.

• Load

❖ Load should be distributed such that low value should occur number of times than high.

❖ Reference Model: If the Load is high output variable should be datain.

• Mode

❖ Mode can be equally distributed.

❖ Reference Model:

▪ UP: if mode is high then if output variable is “11” then output variable made equal to
“0” otherwise increment by “1”.
▪ DOWN: if mode is low then if output variable is “0” then output variable made equal to
“11” otherwise decrement by “1”.
• Datain

❖ Datain is randomized such that value of datain should be in the range of 0 to 11.

• Dataout

❖ Score board: Dataout is compared with the output variable in reference model.

Transaction:
• Random: Reset, Mode, Load, Datain
Transactors:
• Generator: Generates random transaction.
• Driver: Drives Reset, Load, Mode and Datain signals.
• Monitor: collects the Dataout and random transactions.
• Reference Model: Mimic the design inside the environment from transaction data which is
collected in the monitor.
• Scoreboard: Compares the data in reference model and Dataout generated in the design and
generates coverage.

Coverage Model:
• Reset {implicit bins}
• Load {implicit bins}
• Mode {implicit bins}
• Datain {explicit bin [bin range [0:11]]}
• Dataout {explicit bin [bin range [0:11]]}
• Load X Datain
• Mode X Load X Datain

Call backs:
• Scoreboard : Callback triggers the coverage model.
Mod-12 Loadable Up/down counter Source Code

//---------------------RTL-----------------------

module mod12(clk,rst,datain,dataout,load,mode);
input [3:0]datain;
input clk,rst,load,mode;
output reg [3:0]dataout;

always@(posedge clk)
begin
if(rst)
dataout <= 4'b0000;
else
begin
if(load)
dataout <= datain;
else
begin
if(mode)
begin
if(dataout == 4'b1011)
dataout <= 4'b0000;
else
dataout <= dataout + 1;
end
else
begin
if(dataout == 4'b0000)
dataout <= 4'b1011;
else
dataout <= dataout - 1;
end
end
end
end
endmodule

//----------------------------Interface-------------------------

interface count_if(input bit clk);

logic [3:0]datain;
logic [3:0]dataout;
logic rst;
logic load;
logic mode;

clocking dr_cb@(posedge clk);


default input #1 output #1;

output rst;
output datain;
output load;
output mode;
endclocking

clocking wr_cb@(posedge clk);


default input #1 output #1;
input rst;
input datain;
input load;
input mode;
endclocking

clocking rd_cb@(posedge clk);


default input #1 output #1;
input dataout;
endclocking

modport drv(clocking dr_cb);


modport wr_mon(clocking wr_cb);
modport rd_mon(clocking rd_cb);

endinterface

package pkg;
int no_of_trans=1;
endpackage

import pkg::*;

//------------Transaction-----------------

class trans;
rand bit rst;
rand bit mode;
rand bit load;
rand bit [3:0]datain;

bit [3:0]dataout;

static int no_of_rst;


static int no_of_load;
static int no_of_upcount;
static int no_of_downcount;

constraint c1{datain inside{[0:11]};}


constraint c2{load dist{1:=30 , 0:=70};}
constraint c3{mode dist{0:=50 , 1:=50};}
constraint c4{rst dist{1:=30, 0:=70};}

function void display(input string message);


$display("message=%s",message);
$display("datain=%d",datain);
$display("dataout=%d",dataout);
$display("mode=%d",mode);
$display("load=%d",load);
$display("reset=%d",rst);
endfunction

function void post_randomize();

if(this.rst==1||this.rst==0)
no_of_rst++;
if(this.load==1 || this.load==0)
no_of_load++;
if(this.mode==1)
no_of_upcount++;
if(this.mode==0)
no_of_downcount++;
this.display("randomized data");
endfunction

endclass

//-----------------Generator-------------------

class cou_gen;

trans tr;
trans data2send;

mailbox #(trans) gen2dr;

function new(mailbox #(trans) gen2dr);


this.gen2dr=gen2dr;
this.tr=new();
endfunction

virtual task start();


fork
begin
for(int i=0;i<no_of_trans;i++)
begin
assert(tr.randomize());
data2send=new tr;
gen2dr.put(data2send);
end
end
join_none
endtask

endclass

//------------------Write Driver------------------------

class write_driver;
virtual count_if.drv dr_if;
trans data2duv;

mailbox #(trans)gen2dr;
function new(virtual count_if.drv dr_if, mailbox #(trans) gen2dr);

this.dr_if=dr_if;
this.gen2dr=gen2dr;
endfunction

virtual task drive();


begin
@(dr_if.dr_cb);
dr_if.dr_cb.load <= data2duv.load;
dr_if.dr_cb.datain <= data2duv.datain;
dr_if.dr_cb.mode <= data2duv.mode;
end
endtask

virtual task start();


fork
forever
begin
gen2dr.get(data2duv);
drive();
end
join_none;
endtask
endclass

//------------------Write monitor--------------------

class write_monitor;
virtual count_if.wr_mon wr_mon_if;
trans wr_data;
trans data2rm;

mailbox #(trans)mon2rm;

function new(virtual count_if.wr_mon wr_mon_if, mailbox


#(trans)mon2rm);
this.wr_mon_if=wr_mon_if;
this.mon2rm=mon2rm;
this.wr_data=new();
endfunction

virtual task monitor();


begin
@(wr_mon_if.wr_cb)
begin
wr_data.mode = wr_mon_if.wr_cb.mode;
wr_data.load = wr_mon_if.wr_cb.load;
wr_data.datain = wr_mon_if.wr_cb.datain;
wr_data.display("from write monitor");
end
end
endtask

virtual task start();


fork
forever
begin
monitor();
data2rm=new wr_data;
mon2rm.put(data2rm);
end
join_none
endtask

endclass

//----------------------------------Read monitor--------------------

class read_monitor;
virtual count_if.rd_mon rdmon_if;

trans data2sb;
trans rd_data;

mailbox #(trans) mon2sb;

function new(virtual count_if.rd_mon rdmon_if,mailbox


#(trans)mon2sb);
this.rdmon_if=rdmon_if;
this.mon2sb=mon2sb;
this.rd_data=new();
endfunction

virtual task monitor();


begin
@(rdmon_if.rd_cb);
begin
rd_data.dataout=rdmon_if.rd_cb.dataout;
rd_data.display("from the read monitor");
end
end
endtask

virtual task start();


fork
begin
monitor();
data2sb=new rd_data;
mon2sb.put(data2sb);
end
join_none
endtask

endclass

//--------------------Reference Model--------------------------

class count_model;

trans w_data;
static logic [3:0] ref_count=0;

mailbox #(trans) wrmon2rm;


mailbox #(trans) rm2sb;

function new( mailbox #(trans) wrmon2rm, mailbox #(trans) rm2sb);


this.wrmon2rm=wrmon2rm;
this.rm2sb=rm2sb;
endfunction

virtual task count_mod(trans model_counter);


begin
if(model_counter.rst==1)
ref_count<=0;
else
begin
if(model_counter.load)
ref_count <=model_counter.datain;
wait(model_counter.load==0)
begin
if(model_counter.mode==1)
begin
if(ref_count>12)
ref_count<=4'b0000;
else
ref_count<=ref_count+1'b1;
end
else if(model_counter.mode==0)
begin
if(ref_count==0)
ref_count<=4'd11;
else
ref_count<=ref_count-1'b1;
end
end
end
end
endtask

virtual task start();


fork
forever
begin
wrmon2rm.get(w_data);
count_mod(w_data);
w_data.dataout=ref_count;
rm2sb.put(w_data);
end
join_none
endtask

endclass

//-----------------------------ScoreBoard-------------------------

class count_sb;
event DONE;

trans sb_data;
trans rm_data;
trans cov_data;

mailbox #(trans) ref2sb;


mailbox #(trans) rdm2sb;

static int ref_data=0;


static int rmdata=0;
static int data_verified=0;

covergroup counter_coverage;
reset : coverpoint cov_data.rst;
Load : coverpoint cov_data.load;
Mode : coverpoint cov_data.mode;
IN : coverpoint cov_data.datain { bins datain = {[0:11]};}
OUT : coverpoint cov_data.dataout { bins dataout = {[0:11]};}
ldxdin : cross Load,IN;
moxldxxin: cross Mode,Load,IN;
endgroup

function new(mailbox #(trans) ref2sb, mailbox #(trans) rdm2sb);


this.ref2sb=ref2sb;
this.rdm2sb=rdm2sb;
counter_coverage=new();
endfunction

virtual task start();


fork
forever
begin
ref2sb.get(rm_data);
ref_data++;
rdm2sb.get(sb_data);
rmdata++;
check(sb_data);
end
join_none
endtask

virtual task check(trans rdata);


begin
if(rm_data.dataout==rdata.dataout)
$display("data matched");

else
$display("data not matched");
end
cov_data=rm_data;
counter_coverage.sample();

data_verified++;
if(data_verified >= no_of_trans+2);
begin
-> DONE;
end
endtask

virtual function void report();


$display("%d",rm_data);
$display("%d",data_verified);
endfunction

endclass

//--------------------Environment-----------------------

class con_env;

virtual count_if.drv dr_if;


virtual count_if.wr_mon wrmon_if;
virtual count_if.rd_mon rdmon_if;

mailbox #(trans)gen2dr=new();
mailbox #(trans)mon2rm=new();
mailbox #(trans)mon2sb=new();
mailbox #(trans)rm2sb=new();

cou_gen gen;
write_driver wr_dr;
write_monitor wr_mo;
read_monitor rd_mo;
count_model c_mo;
count_sb c_sb;

function new(virtual count_if.drv dr_if,


virtual count_if.wr_mon wrmon_if,
virtual count_if.rd_mon rdmon_if);
this.dr_if=dr_if;
this.wrmon_if=wrmon_if;
this.rdmon_if=rdmon_if;
endfunction

virtual task build();


gen=new(gen2dr);
wr_dr=new(dr_if,gen2dr);
wr_mo=new(wrmon_if,mon2rm);
rd_mo=new(rdmon_if,mon2sb);
c_mo=new(mon2rm,rm2sb);
c_sb=new(rm2sb,mon2sb);
endtask

virtual task start();


gen.start();
wr_dr.start();
wr_mo.start();
rd_mo.start();
c_mo.start();
c_sb.start();
endtask

virtual task stop();


wait(c_sb.DONE.triggered);
endtask

virtual task run();


start();
stop();
c_sb.report();
endtask
endclass

//-----------------------Test cases--------------------------------

class test;

virtual count_if.drv dr_if;


virtual count_if.wr_mon wrmon_if;
virtual count_if.rd_mon rdmon_if;

con_env env;

function new ( virtual count_if.drv dr_if,


virtual count_if.wr_mon wrmon_if,
virtual count_if.rd_mon rdmon_if);
this.dr_if=dr_if;
this.wrmon_if=wrmon_if;
this.rdmon_if=rdmon_if;
env=new(dr_if,wrmon_if,rdmon_if);
endfunction

virtual task build();


env.build();
endtask

virtual task run();


env.run();
endtask

endclass

//--------------------------------Top Module------------------------

module top();
reg clk;
count_if duv_if(clk);
con_env te;

mod12
DUV(.clk(clk),.datain(duv_if.datain),.load(duv_if.load),.mode(duv_if
.mode),.rst(duv_if.rst),.dataout(duv_if.dataout));

initial
begin
clk=1'b0;
forever
#10 clk=~clk;
end

initial
begin
if($test$plusargs("TEST1"))
begin
te=new(duv_if,duv_if,duv_if);
no_of_trans=2000;
te.build();
te.run();
$finish;
end

if($test$plusargs("TEST2"))
begin
te=new(duv_if,duv_if,duv_if);
no_of_trans=2000;
te.build();
te.run();
$finish;
end
end
endmodule
SNIPPET

Q.1 ) What will be the output.

module tb;
reg[2:0] a;
initial

begin
$display("Display : =%0d",a);
a=3;
$strobe("Strobe = %0d",a);
end

endmodule

Output : Display : =x //$display print immediate value

Strobe = 3 //display value at the end of current simulation time

Q.2) What will be the output

module tb;
reg[2:0] a;

initial
begin
$display("Display : %0d",a);
a=3;
$monitor("monitor : %0d",a);

$strobe("strobe : %0d",a);
#10
a=2;
end
endmodule
Output :
Display : x // display immediate value
monitor : 3 // monitor every values and update it
strobe : 3 // print at the end of current simulation time
monitor : 2 // changes value from 3 to 2
@shraddha_pawankar 9/8/23

Que 1) What is the time period for below code?

`timescle 1ns/1ns

#2.3 clk=0;

#1.4 clk=1;

Ans : the code snippet represents events occurring at specific simulation


time points, but it doesn't provide information about the overall time
period or duration of the simulation.

Q 2) what is the output of code

always@(posedge clk,negedge reset)

initial begin

a=0;

a<=1;

$display("value of a=%b",a);

End

…………………….
module test;
reg clk;
reg reset;

reg a;

// Simulate a clock signal


always begin
#5 clk = ~clk; // Toggle the clock every 5 time units
@shraddha_pawankar 9/8/23

end

initial begin

clk = 0;
reset = 0;
a = 0;

// Simulate reset and clock behavior

#3 reset = 1; // Assert reset after 3 time units


#7 reset = 0; // Deassert reset after 7 more time units

// Simulate the always block


@(posedge clk or negedge reset) // Wait for a clock posedge or reset negedge

a = 0;
@(posedge clk or negedge reset) // Wait for another clock posedge or reset negedge
a <= 1;

// Display the value of 'a'

$display("value of a=%b", a);

// End simulation
$finish;
end

endmodule

Output : Value of a=0

https://edaplayground.com/x/QTiQ

Q 3) What is the output


@shraddha_pawankar 9/8/23

module tb;

string a1="System verilog";

$display("%0s",a1);

endmodule

Output : System verilog

Que 4) What is the output

output reg [3:0] a;

initial begin a = 4'b110x;

y = (a == 4'b1100) ? 2'b01 : 2'b11;

end

Output :

a = 4'b110x;: Initializes register a with the value 4'b110x , where x is a don't-care value. This
means that the value of a is either 4'b1100 , 4'b1101 , 4'b1110 , or 4'b1111 .

. If a is equal to 4'b1100 , then y is assigned the value 2'b01 ; otherwise, it is assigned the value
2'b11 .

Que 5) Assign a=c?(b:'b0); what will be the optimized hardware

The expression a = c ? b : 4'b0 represents a conditional assignment in Verilog. It assigns


the value of b to a if condition c is true, and assigns 4'b0 (binary zero) to a if the condition c
is false.

this conditional assignment can be implemented using multiplexers (MUXes) in the


hardware.

Que 6) What is the output

initial begin

a = 5;

a = #10 10;

a = #20 20;

a = #30 30;

for (i = 0; i < 2; i = i + 1)

#3 a = a + 3;
@shraddha_pawankar 9/8/23

End

a = 5; : Initializes the signal a with the value 5.

a = #10 10; : Delays the assignment by 10 time units after the start of simulation and then
assigns the value 10 to a .

a = #20 20; : Delays the assignment by 20 time units after the start of simulation and then
assigns the value 20 to a .

a = #30 30; : Delays the assignment by 30 time units after the start of simulation and then
assigns the value 30 to a .

The loop: It iterates twice (i goes from 0 to 1), and within each iteration, it delays by 3 time
units and increments the value of a by 3.

At time 0, simulation starts. a is initialized to 5.

At time 10, a is assigned the value 10 (due to the #10 delay).

At time 30, a is assigned the value 20 (due to the #20 delay).

At time 60, a is assigned the value 30 (due to the #30 delay).

At time 63, a is incremented to 33. (two iteration)

At time 66, a is incremented to 36.

Iteration ends

Que 7) explain the output and how to get -10 as output?

reg [3:0] a;

a = -10; // consider decimal 2 (2’s complement of 0010)

$display(a);

Explaination:

reg [3:0] a;: Declares a 4-bit wide register a .

a = -10; : Initializes the register a with the decimal value -10

In 4-bit two's complement representation, -10 is equivalent to binary 1110 .

$display(a);: Displays the value of a .

………………

Therefore, the binary value 1110 in a 4-bit signed two's complement representation
represents the decimal value -2 , not -10 .
@shraddha_pawankar 9/8/23

If you want to represent -10 in a 4-bit signed binary number, you would need to use a larger
bit-width (e.g., 5 bits) to accommodate the necessary range.

Que 8) what is wrong with the code ?

forever begin

a=a+1;

b=b+1;

end

Explaination:

The problem is that this forever loop creates an infinite loop that continuously updates the
values of a and b .

We have to terminate the simulation

Que 9) Detect the bugs in the given code ?

always@(posedge clk,reset)

begin

if(reset==1)

q <=0;

else

q<= clk;

end

The corrected code

always @(posedge clk, posedge reset) begin

if (reset == 1)

q <= 0;

else

q <= clk;

end

Que 10) why is it "if(2'b01 & 2'b10)" doesnt run the true case

The bitwise AND operation compares each bit of the operands


@shraddha_pawankar 9/8/23

Since the result of 2'b01 & 2'b10 is 2'b00 , which is 0 , the "true" case of the if statement
won't be executed. This is why the "true" case doesn't run.

Que 11) find output "a" in the following snippet.

reg[4:0] a;

a[2:1]=2'b1x;

a[2:1] : Refers to bits 2 to 1 (inclusive) of the 5-bit register a .

2'b1x : Represents a 2-bit binary value where the first bit is 1 and the second bit is a don't-
care value x .

a[2:1] = 2'b1x; , the bits 2 and 1 of a are set to 1 and x (don't-care), respectively. The rest of
the bits in a remain unaffected by this assignment.

Que 12) Which of the following evaluates the RHS but does not set the valuee of the
LHS until the next time step.in the below snippet at what time unit c gets value 1.

code 1:

module

begin a=#10 1'b1;

b=#20 1'b0;

c=#40 1'b1;

end

endmodule

code 2:

module

begin

a<=#10 1'b1;

b<=#20 1'b0;

c<=#40 1'b1;

end

endmodule

In Verilog, the non-blocking assignment (<= ) operator schedules an assignment to occur in


the next time step,
@shraddha_pawankar 9/8/23

while the blocking assignment (= ) operator causes the assignment to take effect
immediately

if you want to evaluate the RHS but delay the update of the LHS until the next time step, you
should use the non-blocking assignment (<= ) operator.

module

begin

a <= #10 1'b1;

b <= #20 1'b0;

c <= #40 1'b1;

end

endmodule

So, in the provided code snippet, c gets the value 1 at simulation time 40 .

Q 13) find the output of the following snippet?

initial begin

a=#1 1'b1;

b=#2 1'b0;

c=#4 1'b1;

end

initial begin

a<=#1 1'b1;

b<=#2 1'b0;

c<=#4 1'b1;

end

consider Snippet 1:

initial

begin

a = #1 1'b1;

b = #2 1'b0;
@shraddha_pawankar 9/8/23

c = #4 1'b1;

end

output :

At time 0: a=x, b=x, c=x

At time 1: a=1, b=x, c=x

At time 2: a=1, b=0, c=x

At time 3: a=1, b=0, c=x

At time 4: a=1, b=0, c=1

consider Snippet 2:

initial

begin

a <= #1 1'b1;

b <= #2 1'b0;

c <= #4 1'b1;

end

Output:

At time 0: a=x, b=x, c=x

At time 1: a=1, b=x, c=x

At time 2: a=1, b=0, c=x

At time 3: a=1, b=0, c=x

At time 4: a=1, b=0, c=1

Both snippets will produce the same output because the values of a , b, and c are not being
changed after their initial assignments.

Que 14) consider the below given example and find the output?

initial

begin
@shraddha_pawankar 9/8/23

a=1;

end

initial

begin

a=3;

end

Explaination:

In Verilog, if multiple initial blocks are present in the same scope, their behavior is non-
deterministic.

The order of execution of these initial blocks is not guaranteed.

This means that you cannot predict with certainty which initial block will execute first.

Here are the two possible scenarios:

Scenario 1 (Initial Block 1 Executes First): Final value of a = 3

Scenario 2 (Initial Block 2 Executes First): Final value of a = 1

Que 15) consider the snippet and find the inferred synthesized circuit?

if(a==1)

c=1;

else

c=2;

The inferred synthesized circuit for the provided code snippet would look like a 1-bit MUX
with two data inputs (1 and 2) and a select input (a).

Depending on the value of a , the MUX will select either input 1 or input 2 to drive the output
c.

Que 16) what is the output of following snippet?

q.size=10;

begin

for(i=0;i<q.size;i++)

q.pop_back();
@shraddha_pawankar 9/8/23

end

in this snippet, the code sets the size property of q to 10 and then enters a loop that iterates
from i = 0 to i < q.size (which is 10).

Within the loop, q.pop_back() is called in each iteration, which might suggest that the loop is
intended to remove elements from the back of the data structure.

Q 17) if a=3'b1x0 then d=|a; what is the value of d?

1. If a is 3'b100 (where x is assigned the value 0):


 d = |a = |3'b100 = 1
2. If a is 3'b110 (where x is assigned the value 1):
 d = |a = |3'b110 = 1

Q 18) what is the meaning of @(posedge clk) a|=>b;

The syntax @(posedge clk) a |=> b; is not valid Verilog syntax.

Correct syntax:

always @(posedge clk)

b <= a;

Q 19) if the clock has 2ns as its time period,how much is #10 delay?

If the time period of the clock is 2ns (nanoseconds), then the delay #10 corresponds to a
simulation time of 10 * 2ns = 20ns.

Q 20) if a=3'b0xx what will be the value displayed in the below verilog snippet

always@*

begin

casex(a)

3'b01? :$display("1 to 0");

3'b0?? :$display("2 to 3");

endcase

end

The pattern 3'b01? means that the first two bits of a must be 01 , and the third bit can be
anything (0 or 1).

The pattern 3'b0?? means that the first bit of a must be 0 , and the second and third bits can
be anything (0 or 1).
@shraddha_pawankar 9/8/23

Since the value of a is 3'b0xx, it satisfies both patterns. It starts with 01 and has a 0 in the first
bit.

When the casex statement is evaluated, it will match both patterns, but the patterns are not
mutually exclusive. The casex statement in Verilog will execute the first matching pattern and
ignore the subsequent patterns that might also match.

Output : 1 to 0

Q 21) which block executes in the below snippet and justify the reason

reg[3:0]a=4'b110x;

initial

begin

if(a==4'b1100)

begin: B1

end

else

begin : B2

end

end

== logical equality cant merge with X and Z .Hence the condition returns ambiguous
result,due to which else branch will be executed.

Q 22) which block executes in the below snippet and justify the reason

reg[3:0]a=4'b110x;

initial

begin

if(a!==4'b1100)

begin: B1

end

else

begin : B2
@shraddha_pawankar 9/8/23

end

end

!== case inequality can merge with X and Z .

110X

1100

…………

Doent match and returns true value.

Block B1 will execute.

Q 23) What is the value of X in the below snippet.

reg[3:0]a=4'b0100;

reg[3:0]b;

initial

begin

b=a+1'bx;

end

Output : X

X add with anything result =x

Que 24) What is the value of y in the below expression and justify the reason

reg[3:0]a=4'b010x;

wire y=(a==4'b1100)?1'b1:1'b0;

Result : 0

Que 25) Evaluate the value of X in the below snippet

reg[3:0] a;

reg[1:0] x;

initial
@shraddha_pawankar 9/8/23

begin

a=4'd10;

x=(a>>1);

end

>> right shift.

Logical right shift the vacant bit must be filled with 0.

(10)d=1010 after right shift 0101

Que 26) find the value of b in the below snippet?

reg[3:0] a;

reg[6:0] b;

initial

begin

a=4'd10;

b={a,1} //b=7bit

end

b=7’b000_0001

Que 27) What is the value of X in the below snippet?

reg[2:0] a,b;

reg [2:0] x;

initial

begin

a=3'd5;

b=3'b111;

x=a|b;

end
@shraddha_pawankar 9/8/23

| Bitwise OR

101

111

……….

111

Result: X=3’b111;

Q 28) What is the value of X in the below snippet

reg[2:0] a;

reg[2:0] x;

initial

begin

a=3'd4;

x=^a;

end

^a = reduction XOR operation

(4)d=100=1^0^0=1

Q 29) What is the value of y in the below snippet?

reg[2:0]a,b;

reg y;

initial

begin

a=3'd5;

b=3'b111;

y=a&&b;

end
@shraddha_pawankar 9/8/23

&& logical and

Y=1[True value && True value]

Q 30) What is the value of y in binary format in the below snippet

reg[5:0]y;

initial

begin

y='0x2;

end

y is total 6 bit

y=6’bxxx_010

Q 31) What is the value of b in the below expression

integer b;

initial

begin

b=-'d12/3;

end

2^32-12/3=1431655

Negative integers are stored as 2’s complement if base specifier is given

Q 32) What value is passed across the port b in the below snippet.

module test(output[32:0]b);

real a=14.5;

assign b=a;

endmodule
@shraddha_pawankar 9/8/23

A value of 14 will be passed(The fractional part will be truncated since,the real numbers
cant be directly passed across the interfaces)

Q 33) What is the output

reg[3:0] var1;

initial

begin

var1=-5;

$display(var);

End

Reg cannot stored negative value

5=0101

2’s complement of 0101=1011=(11)d

Display=(11)d

Q 34) reg clk;

initial clk=0;

always@(clk) clk=~clk;

clk=X;

clk=0;

one time always block executed

Q 35) reg clk;

initial clk=0;

always@(clk) clk<=~clk;

Multiple time always block executed

Q 36) What is the output

always @(a or x)

begin
@shraddha_pawankar 9/8/23

if(a)

begin

x=x+1'b1;

end

else

begin

x=x;

end

generating latch

Q 37) How many D ff will be inferred from the below snippet

input C,din;

output reg y3;

reg y1,y2;

always@(posedge c)

begin

y1=din;

y2=y1;

y3=y2;

end

Only 1 D ff,Because of the usage of blocking assignment,din will be assigned to y1 in 1


clock cycle,y2 and y3 will also get the same value

Q 38) How many D ff will be inferred from the below snippet

input C,din;

output reg y3;

reg y1,y2;

always@(posedge c)
@shraddha_pawankar 9/8/23

begin

y1<=din;

y2<=y1;

y3<=y2;

end

3 no. of D flip flop,Because of the usage of nonblocking assignments.

Din will be assigned to y1 in 1 clk cycle

The previous value will be assigned to y2

Q 39) Which of the statement will execute from the below snippet and justify the behavior

reg[2:0]c=3'b00x;

always@(*)

begin

casex(c)

3'b000=st1;

3'b100=st2;

3'b001=st3;

Endcase

This is overlapping case,the first occurred case item will be executed and it infers priority
encoding logic

Hence statement 1 will be executed

Q 40) Which hardware logic is inferred from the below snippet

always@(*)

begin

case(1'b1)

a[3] : y=3;

a[2] : y=2;

a[1] : y=1;

a[0] : y=0;
@shraddha_pawankar 9/8/23

endcase

end

This kind of overlapping cases,it inferes priority encoding logic,

Hence it infers a 4:2 priority encoder

Q41) Find the value of the hardware of the variable t at 1ns and 20 ns respectively from the
below snippet?

time t;

initial

begin

#10 t=$time;

#20;

End

At t=1ns : the value of t variable will be unknown since it is not initialized till 10 ns

At 20 ns: the value of t variable will be 10 since it is updated at time t=10ns and not
updated further

Q 42) What will be the value of the parameter constant for the instance DUT in the top
module in the below snippet?

module test;

parameter width=8;

endmodule

module top

test#(16) DUT();

for the instance DUT of the module test,order based parameter.overriding is being
done.Hence parameter width is changed to 16

Q 43) What is the bug in the following snippet?


@shraddha_pawankar 9/8/23

module test;

parameter width=8;

endmodule

module top;

test DUT();

initial

defparam DUT.width=10;

endmodule

defparam should not be used inside a process as it executed during the elaboration phase
and not in the simulation phase

Q 44) What is the display output?

reg[1:0] a,b;

initial

begin

a<=2'd3;

b<=2'd2;

#10

a<=2'd0;

b<=2'd1;

$monitor("a=%0d b=%0d",a,b);

End

Value of a=0 & b=1

$monitor is called at 10 time units

Will be monitoring the event from current time slot

Q 45) What is the display output?

reg[1:0] a,b;

initial
@shraddha_pawankar 9/8/23

begin

a<=2'd3;

b<=2'd2;

#10

a<=2'd0;

b<=2'd1;

$display("a=%0d b=%0d",a,b);

end

Displaying active event from previous value

A=3 b=2;

Q 46) What is the bug in the following snippet?

reg clock;

initial

begin

#10 clock=0;

end

always@clock;

clock=#10 ~clock

Blocking assignment used within the always process cant trigger active event

Q 47) What will be the display

reg [2:0] a;

initial

begin

$display("Display:%0d",a);

a=3;

$strobe("strobe:%0d",a);

End
@shraddha_pawankar 9/8/23

Display=x

Strobe=3

Q 48) What will be the display

reg[2:0]a;

initial

begin

$display("Display:%0d",a);

a=3;

$monitor("Monitor:%0d",a);

$strobe("strobe:%0d",a);

#10

a=2;

end

Display : X

Monitor:3

Strobe:3

Monitor:2

Q 49) At what simulation time

initial

begin : A1

#10;

#20;

#40;

end

initial

fork : A2

#10;
@shraddha_pawankar 9/8/23

#20;

#40;

Join

At 70 time unit : A1 Begin-end -sequential block-delays are added

At 40 time unit : A2 Fork – join -parallel block -delays are non additive

Q 50) At what time the statement “a” executes?

module test;

reg a=1;

reg b=0;

task t1;

begin

forever

begin

#10 b<=a;

#10 a<=b;

end

endtask

initial begin

fork

t1;

join

#5 a<= ~a;

end

endmodule

The task t1 is called inside fork join block

The task t1 has forever loop

The task never exists,the fork join block also never exists.
@shraddha_pawankar 9/8/23

The statement a will never execute

Q 51) In parameter the left hand side can be……………….

Reg and integer

Parameter constant can be any datatype except wire

Q 52) What datatype should be used for y in the below code to avoid error contention

Assign y=b&c;

Assign y=a^g;

WOR – used when parallel drivers are driving a common mode

Q 53) What will be the output

reg clk;

always

begin

clk=~clk;

end

clock has no initial state

reg default datatype is X

Q 54) Explain the term out=repeat(8) @(posedge clk) b;

The value b is evaluated at the current simulation time but not ssigned to out until
after 8 clock cycles

Q 55) If the 8 bits “x” declared as “reg[7:0] x” is initialized to 8’b10101101,what will be


its value after execution of the following code?

always@(posedge clk)

begin

x<=x<<1;

x[0]<=x[7];

end

x<= x<<1
@shraddha_pawankar 9/8/23

10101101

Left shift => 0101101

Initial value of x[7]=0

X[0]=0
1.0 Verilog Synthesis Methodology
Finbarr O’Regan ([email protected]) October 2001

Synthesis is a contraint driven process i.e. the synthesis script needs timing constraints

Follow the following methodology for best results


1. Draw a simple block diagram, labelling all signals, widths etc.
2. Draw a timing diagram with as much detail as possible
3. Code the HDL according to the synthesizable templates
4. Do a quick, low effort, compile- just to see if it is synthesizable before simulating. Compare this to the block dia-
gram. Look at the inference report:
• count the number of flip flops - is it the same as the number of flip flops in the code.
• check for latches - did you want them. If not, latches are inferred in combinational procedures - the inferrence
report tells you which combinational procedure and the name of the latch. Fully specify all variables in all cases to
eliminate latches.
• Check the case statement inferrence. Was it full/parallel?
• Check any incomplete event list warnings?
• Check to see if there are any combinational feedback loops (typically only after a compile). Combinational feed-
back loops can be identified by the signal names in the timing loop.
• Check the schematic - any ports unconnected?
• Check to see if Designware and Ambitware components have been built correctly. Are these the components that
you wanted? How many did you want?
• Never ignore any warning that the synthesis tool flags. All warnings need to be understood and typically signed
off.
5. Simulate and compare with the timing diagram
• If your design doesn’t meet timing by more than 10% of the clock period, then go back to the code. If you are
within 10% of the clock period, then try a different compile strategy.

October 18, 2001 1


2.0 Synthesizeable Templates
2.1 Combinational Logic

a
b c

// Using a reg
// -----------------------------
wire a,b;
reg c;
always @ (a or b)
c = a & b;

// Using a wire
// -----------------------------
wire a,b,c;
assign c = a & b;

// using a built in primitive (without instance name)


// -----------------------------
reg a,b;
wire c;
and (c,a,b); // output is always first in the list

// using a built in primitive (with instance name)


// -----------------------------
reg a,b;
wire c;
and u1 (c,a,b); // output is always first in the list

// if c is an output
// -----------------------------
output c;
reg a,b;
assign c = a & b;

October 18, 2001 2


2.2 Multiplexers

2.2.1 Multiplexer using a procedure

// 1. using an always a
always@(a or b or sel)
1
b
if (sel == 1’b1) c 0
c = a;
else
c = b;
sel
Use default assignments
to prevent latches: every

2.2.2 Multiplexer using the ternary operator

// 2. using the ternary operator


wire c = sel ? a : b;

2.2.3 Multiplexer using the case statement

// 3. using the case statement a


1
always @ (a or b or sel) b
case (sel) c 0
1’b1: c = a;
1’b0: c = b;
sel
endcase

October 18, 2001 3


2.3 Priority Decoders

2.3.1 Priority Decoder using a case statement


// 1. using a case statement
always @ (sl or a or b or c) 1. Both case and if statements result in
priority structures.
case (sel)
2. The order of the variables determines
2’b11: d = a;
the priority
2’b10: d = b;
default: d = c;
endcase

sel
2’b10 2’b11
2

= =

c 0
0
b 1 d
1
a

October 18, 2001 4


2.3.2 Priority Decoder using an if/else statement

// 2. using an if statement
always @ (sl or a or b or c)
if (sel == 2’b11)
d = a;
else if (sel ==2’b10)
d = b;
else
d = c;

sel
2’b10 2’b11
2

= =

c 0
0
b 1 d
1
a

October 18, 2001 5


2.4 Parallel Priority Decoders

2.4.1 Parallel Priority Decoders Using a Synthesis Directive

// using a synthesis directive


always @ (sl or a or b or c)
case (sel) // parallel_case
2’b11: d = a;
2’b10: d = b;
default:d = c; sel
endcase
2

c 2’b0x
b 2’b10 d
a 2’b11

October 18, 2001 6


2.5 Bus Logic, Splitting and Reordering

2.5.1 Bus Enabling

// A1. using a wire


wire [3:0] d = ({4{enable}} & c);
// A2. using a reg
reg [3:0] d;
always @ (c or enable)
d = c & {4{enable}};

enable
d[3:0]
c[3:0]
4
4

October 18, 2001 7


2.5.2 Bus Concatenation

// B1. using a wire


wire [2:0] e = {a[1],b[3:2]};
// B2. using a reg
reg [2:0] e;
always @ (a or b)
e = {a[1],b[3:2]};

e = {a[1],b[3:2]}
a[3]
a[2]
a[1] e[2]
a[0] e[1]
b[3] e[0]
b[2]
b[1]
b[0]

October 18, 2001 8


2.5.3 Bus Replication

a[0] b[0]
a[1] b[1]
b[2]
b[3]

// bus replication
wire [1:0] a;
wire [3:0] b;
assign b = {2{a}};

October 18, 2001 9


2.6 Comparators
// 1. using a wire
wire d;
assign d = (a == c);

// 2. using a reg
reg d;
always @ (a or c)
d = (a == c);

a[3:0]
4
= 1
d
c[3:0]
4

October 18, 2001 10


2.7 D Type Flip Flops

// 1. positive edge triggered D flip flop


always @ (posedge clock)
q <= d;

d q

Use non-blocking assignments (<=) in


clock
clocked procedures.

// 2. negative edge triggered D flip flop


always @ (negedge clock)
q <= d;

d q

clock

October 18, 2001 11


2.8 Resettable D Type Flip Flops
// 1. synchronously resettable D flip flop
always @ (posedge clock)
if (reset)
q <= 1’b0;
else 1’b0
q <= d;
q
d

reset

clock

// 2. asynchronously resettable D flip flop


// (active high async reset)
always @ (posedge clock or posedge reset)
if (reset)
reset
q <= 1’b0;
else
q <= d; d q

clock

October 18, 2001 12


// 3. asynchronously resettable D flip flop
// (active low reset)
always @ (posedge clock or negedge reset)
if (~reset)
q <= 1’b0; reset
else
q <= d; d q

clock

October 18, 2001 13


2.9 Data Enabled and Clock Gated Flip Flops
// 1. data enabled flip flop
always @ (posedge clock)
if (enable)
q <= d;

q
d

enable

clock

// 2. D flip flop with gated clock


wire gclk = (clock && enable);
always @ (posedge gclk)
q <= d;

d q

clock
enable
gclk
enable signal must be
glitch free

October 18, 2001 14


2.10 Latches
// 1. latch
always @ (enable or d)
if (enable)
q = d; d q

enable
// 2.resettable latch
always @ (enable or d or reset)
if (reset)
q = 1’b0;
reset
else if (enable)
q = d;
d q

enable

October 18, 2001 15


2.11 Tri-state Drivers
// 1. using a reg
reg y;
always @ (d or enable)
enable
if (enable)
y = d; d y
else
y = 1’bz;

// 2. using a wire
wire y;
assign y = enable ? d : 1’bz;

// 3. using a primitive
bufif1 (y,d,enable);

October 18, 2001 16


2.12 Counter
3 bit asynchronously resettable counter which counts 0, 1, 2, 3, 4, 5,
// 3 bit asynchronously resettable
// partial range counter
always @ (posedge clock or posedge reset)
if (reset)
count <= 3’b0;
else
if (count == 3’b101)
count <= 3’b0;
else
count <= count + 3’b001;

reset
3’b001
3’b000 count
1
0 3
3
enable

=
3’b101
clock

October 18, 2001 17


2.13 Enabled Shift Register

data_out
data_in

clock
enable

module enabled_shift_reg (clock,enable,data_in,data_out);


input clock;
input enable;
input [3:0] data_in;
output [3:0] data_out;

reg [3:0] data_out;


reg [3:0] shift_reg_1;
reg [3:0] shift_reg_2;
reg [3:0] shift_reg_2;

always @ (posedge clock)


if (enable)
begin
shift_reg_1 <= data_in;
shift_reg_2 <= shift_reg_1;
shift_reg_3 <= shift_reg_2;
data_out <= shift_reg_3;
end

endmodule

October 18, 2001 18


2.14 Unsigned Adders and Multipliers
a
5
c
6

12
b e
5
6
d

Note that the * and + and - signs give you unsigned arithmetic. If you need signed arithmetic, you may need special
instaces recognizable to the synthesis tool.
• Adding two five bit numbers gives a siz bit result (the extra bit is the carry out bit).
• The multiplication of two number means that the output is twice the width of the inputs.

wire [5:0] c = a + b;
wire [11:0] e = c * d;

October 18, 2001 19


3.0 Coding Guidelines
These coding guidelines assume that you are able to write correct synthesizeable code. You can always check the
synthesizeablilty of your code by parsing it using the synthesis tool.
• Use non-blocking assignments (<=) in clocked procedures. Don’t use blocking assignments (=).
always @ (posedge clock)
q <= d;

• Use blocking assignments (=) in combinational procedures:


always @ (a or b or sl)
if (sl)
d = a;
else
d = b;

• Make sure that the event lists are complete


always @ (a or b) // this event list is missing signal sl
if (sl)
d = a;
else
d = b;
• Take care of indentation. Develop your own identation guidelines and stick to them. Make sure others can read
them. It helps readability and debugging greatly if it is done properly.
• Comment code properly. The theory about good commenting is that you should be able to remove all functional
code and the comments remaining should almost document the block you are designing.
// example of bad comments
// add a and b together
always @ (a or b)
c = a + b;

// Good commenting
// 8 bit unsigned adder for data signals ‘a’ and ‘b’
// output is sent to UART2
always @ (a or b)
c = a + b;

• Always completely specify literals.


always @ (c)
if (c == 4’b0101)
a = 2’bxx;
else
a = 2’b10;
• Use named port mapping when instantiating.
state_machine u1 (
.sm_in (in1),
.sm_clock (clk),
.reset (reset),
.sm_out (data_mux)
);

• Don’t make the code any more complicated than it needs to be. Your priorities should be correctness, then read-
ability and finally code efficiency.

October 18, 2001 20


4.0 State Machine Guidelines
4.1 Guidelines
• Draw a state diagram.
• Label the states.
• Allocate state encoding.
• Label the transition conditions.
• Label the output values.
• Use parameters for the state variables.
• Use two procedures (one clocked for the state register and one combinational for the next state logic and the out-
put decode logic).
• Use a case statement in the combinational procedure.
• Have a reset strategy (asynchronous or synchronous).
• Use default assignments and then corner cases.
• Keep state machine code separate from other code (i.e. don’t mix other logic in with the state machine clocked
and combinational procedures).

October 18, 2001 21


4.2 State Diagram
transition condition

ack = 1’b0 start ack = 1’b0


offline = 1’b1 IDLE offline = 1’b0
online = 1’b0 online = 1’b1
2’b10 RUN
2’b00
transmit state label

state encoding
wait stop
ack = 1’b1 PAUSE
offline = 1’b0
online = 1’b1 2’b01 output values
FINISH
2’b11 ack = 1’b1
stop offline = 1’b0
online = 1’b1

October 18, 2001 22


4.3 State Machine Verilog Code
module state_machine (clock,reset,start,transmit,wait,stop,ack,offline,online);
// parameter declarations
parameter pIDLE = 2’b10; // state labels and state encoding
parameter pRUN = 2’b00;
parameter pPAUSE = 2’b01;
parameter pFINISH = 2’b11;

// IO declaration section
input clock;
input reset;
input start, transmit, wait, stop;
output ack, offline, online;
// interal variables declaration section
reg [1:0] state, next_state;
reg ack, offline, online;

// clocked procedure with synchronous reset


always @ (posedge clock)
if (reset) // reset strategy
state <= pIDLE;
else
state <= next_state;

// combinational procedure with case statement and output logic


always @ (start or transmit or stop or wait or state)
begin
next_state = state; // default assignment to state and output variables
ack = 1’b0;
offline = 1’b0;
online = 1’b1;
case (state)
pIDLE:
begin
offline = 1’b1;
online = 1’b0;
if (start)
next_state = pRUN;
end
pRUN:
begin
if (wait)
next_state = pPAUSE;
if (stop)
next_state = pFINISH; // this has priority over the wait transition
end
pPAUSE:
begin
ack = 1’b1;
if (transmit)
next_state = pRUN;
if (stop)
next_state = pFINISH;
end
pFINISH:
ack = 1’b1;
endcase
end

endmodule

October 18, 2001 23


VLSI FOR ALL

www.vlsiforall.com
Q1. Write a code to generate clk , with and without loop.

Q2. Design 5 sequential cky in verilog using all 4 modeling.

Ans 1:
VLSI FOR ALL
module clk_generator;

reg clk=0;

always

begin

#5 clk=~clk;

end

initial

begin

$dumpfile("dump.vcd");

$dumpvars;

#100

$finish;

end

endmodule
VLSI FOR ALL
module tb;

int T=10;

reg clk=0;

initial

begin

//for(i=0;i<10;i=i+1)

//repeat(n=infinity)

forever

begin

clk=~clk;

$display("clk=%0d",clk);

#(T/2);

end

www.vlsiforall.com
end

initial

begin
VLSI FOR ALL
$dumpfile("dump.vcd");

$dumpvars;

#100

$finish;

end

endmodule

Output>>>

clk=1

VCD info: dumpfile dump.vcd opened for output.

clk=0

clk=1

clk=0 VLSI FOR ALL


clk=1

clk=0

clk=1

clk=0

clk=1

clk=0

clk=1

clk=0

clk=1

clk=0

clk=1

clk=0

clk=1

clk=0

clk=1

clk=0

www.vlsiforall.com
clk=1

Finding VCD file...

./dump.vcd
VLSI FOR ALL
[2023-07-24 12:55:51 UTC] Opening EPWave...

Output:-

Q2. Desing 5 combinationl ckt in verilog using all 4 modeling.

Gate level Modelling


// Code your design here VLSI FOR ALL
module m21(input d0,d1,s, output y);

wire t1,t2,sbar;

not(sbar,s);

and(t1,sbar,d0);

and(t2,s,d1);

or(y,t1,t2);

endmodule

Testbench

module tb;

wire y;

reg d0,d1,s;

m21 uut(.d0(d0),.d1(d1),.s(s),.y(y));

initial

begin

d0=1'b0;

d1=1'b0;

s=1'b0;

end

www.vlsiforall.com
always #20 d0=~d0;

always #40 d1=~d1;

always #10 s=~s;


VLSI FOR ALL
initial

begin

$dumpfile("dump.vcd");

$dumpvars;

#100

$finish;

end

endmodule

Output wave:

DataFlow Modelling VLSI FOR ALL


module m21(input d0,d1,s,output y);
assign y=(s)?d1:d0;
endmodule

Behavioral Modelling
module m21(input d0,d1,s,output y);
always@(d0 or d1 or s)
begin
if(s)
y=d1;
else

www.vlsiforall.com
y=d0;
end VLSI FOR ALL
endmodule

Structural Modelling
// Code your design here
module and_gate(output d,input c,e);
assign d =c & e;
endmodule

module not_gate(output a,input b);


assign a=~b;
endmodule

module or_gate(output l, input m,n);


assign l=m|n;
endmodule
VLSI FOR ALL
module m21(output y ,input d0,d1,s);
wire t1,t2,sbar;
and_gate u3(t2,s,d1);
not_gate u1(sbar,s);
and_gate u2(t1,sbar,d0);

or_gate u4(y,t1,t2);
endmodule

4 X 1 Mux
Gate level Modelling

www.vlsiforall.com
module m41(output y, input d0,d1,d2,d3,s0,s1);
wire t1,t2,t3,t4,s0bar,s1bar;
not (s0bar,s0),(s1bar,s1);
VLSI FOR ALL
and (t1,s0bar,s1bar,d0),(t2,s0bar,s1,d1),(t3,s0,s1bar,d2);
and (t4,s0,s1);
or (y,t1,t2,t3,t4);
endmodule

module tb;
wire y;
reg d0,d1,d2,d3,s0,s1;

m41 dut(.y(y),.d0(d0),.d1(d1),.d2(d2),.d3(d3),.s0(s0),.s1(s1));
initial
begin
d0=1'b0;
VLSI FOR ALL
d1=1'b0;
s0=1'b0;
d2=1'b0;
d3=1'b0;
s1=1'b0;
end
always #20 d0=~d0;
always #10 d1=~d1;
always #10 s0=~s0;
always #20 d2=~d2;
always #40 d3=~d3;

www.vlsiforall.com
always #10 s1=~s1;

initial
VLSI FOR ALL
begin
$dumpfile("dump.vcd");
$dumpvars;
#100
$finish;
end
endmodule

Output:-

Dataflow Modelling VLSI FOR ALL


module m41(output y, input d0,d1,d2,d3,s0,s1);
assign y=s1?(s0?d3:d2):(s0?d1:d0);
endmodule

Behavorial Modelling
module m41(output y, input d0,d1,d2,d3,s0,s1);
wire d0,d1,d2,d3,s0,s1;

www.vlsiforall.com
reg y; VLSI FOR ALL
always@(d0 or d1 or d2 or d3 or s0,s1)
case (s1|s0)
2'b00:y<=d0;
2'b01:y<=d1;
2'b10:y<=d2;
2'b11:y<=d3;
endcase
endmodule

Structural Modelling
module and_gate(output d,input c,e,f);
assign d =c & e & f;
endmodule
VLSI FOR ALL
module not_gate(output a,input b);
assign a=~b;
endmodule

module or_gate(output l, input m,n,o,p);


assign l=m|n|o|p;
endmodule

module m41(output y, input d0,d1,d2,d3,s0,s1);


wire t1,t2,t3,t4,s0bar,s1bar;
not_gate u1(s0bar,s0),u2(s1bar,s1);
and_gate u3(t1,s0bar,s1bar,d0),u4(t2,s0bar,s1,d1);
and_gate u5(t3,s0,s1bar,d2),u6(t4,s0,s1,d3);
or_gate u7(y,t1,t2,t3,t4);

www.vlsiforall.com
endmodule

VLSI FOR ALL


Full Adder
Gate level Modelling
module fa(output y,cin,input a,b,c);

wire t1,t2,t3;
xor(t2,a,b);
xor(y,t2,c);

and(t1,a,b);

and(t3,t2,c);
or(cin,t1,t3);
endmodule

Testbench Code
VLSI FOR ALL
module testbench_fulladder;
reg a,b,c;
wire s,cin;

fa f1(y,cin,a,b,c);

initial begin
a = 1'b0;
b = 1'b0;
c = 1'b0;
#20;

www.vlsiforall.com
a = 1'b0; VLSI FOR ALL
b = 1'b0;
c = 1'b1;
#20;

a = 1'b0;
b = 1'b1;
c = 1'b0;
#20;

a = 1'b0;
b = 1'b1;
c = 1'b1;
#20;

a = 1'b1;
b = 1'b0;
c = 1'b0;
VLSI FOR ALL
#20;

a = 1'b1;
b = 1'b0;
c = 1'b1;
#20;

a = 1'b1;
b = 1'b1;
c = 1'b0;
#20;
www.vlsiforall.com
a = 1'b1;
b = 1'b1;
c = 1'b1;
VLSI FOR ALL
#20;

$finish;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
#100
$finish;
end

endmodule

VLSI FOR ALL


Dataflow Modelling
module fa(output y,cin,input a,b,c);

assign y=(a^b^c);
assign cin=(a&b) | (c&(a^b));
endmodule
Behavoiral Modelling
module fa(output y,cin,input a,b,c);
reg cin,y;
always@(*)
begin
case({a,b,c})

www.vlsiforall.com
3'b000:y=0;
3'b001:y=1; VLSI FOR ALL
3'b010:y=1;
3'b011:y=0;
3'b100:y=1;
3'b101:y=0;
3'b110:y=0;
3'b111:y=1;
default y=0;
endcase
case({a,b,c})
3'b000:cin=0;
3'b001:cin=0;
3'b010:cin=0;
VLSI FOR ALL
3'b011:cin=1;
3'b100:cin=0;
3'b101:cin=1;
3'b110:cin=1;
3'b111:cin=1;
default cin=0;
endcase
end
endmodule

Structural Modelling
module and_gate(output d,input c,e);
assign d =c & e;
endmodule

module not_gate(output a,input b);

www.vlsiforall.com
assign a=~b;
endmodule
VLSI FOR ALL
module or_gate(output l, input m,n);
assign l=m|n;
endmodule
module xor_gate(output p, input q,r);
assign p= q^r;
endmodule
module fa(output y,cin,input a,b,c);

wire t1,t2,t3;
xor_gate u1(t2,a,b);
xor_gate u2(y,t2,c);

and_gate u3(t1,a,b);
VLSI FOR ALL
and_gate u4(t3,t2,c);
or_gate u5(cin,t1,t3);
endmodule

8 x 3 Encoder
Behavorial Modelling
module en_83(output reg [2:0] y, input [7:0]i, input en);

//reg [2:0]y;
always@(en,i)
begin

www.vlsiforall.com
if(en==1)
begin VLSI FOR ALL
if(i[7]==1) y=3'b111;
else if(i[6]==1) y=3'b110;
else if(i[5]==1) y=3'b101;
else if(i[4]==1) y=3'b100;
else if(i[3]==1) y=3'b011;
else if(i[2]==1) y=3'b010;
else if(i[1]==1) y=3'b001;
else
y=3'b000;
end
else
y=3'bzzz; VLSI FOR ALL
end
endmodule

Testbench

module tb;
reg [7:0]i;
reg en;
wire [2:0]y;

// instantiate the model: creating


// instance for block diagram
en_83 dut(.y(y),.i(i),.en(en));
initial
begin
// monitor is used to display the information.

www.vlsiforall.com
$monitor("en=%b i=%b y=%b",en,i,y);
// since en and i are input values,
// provide values to en and i.
en=1; i=128;#5
en=1; i=64;#5
en=1; i=32;#5 VLSI FOR ALL
en=1; i=16;#5
en=1; i=8;#5
en=1; i=4;#5
en=1; i=2;#5
en=1; i=0;#5
en=0;i=8'bx;#5
$finish;
end
initial
begin VLSI FOR ALL
$dumpfile("dump.vcd");
$dumpvars;
#100
$finish;
end

endmodule
Output:
VCD info: dumpfile dump.vcd opened for output.
en=1 i=10000000 y=111
en=1 i=01000000 y=110
en=1 i=00100000 y=101
en=1 i=00010000 y=100
en=1 i=00001000 y=011
en=1 i=00000100 y=010
en=1 i=00000010 y=001
en=1 i=00000000 y=000
en=0 i=xxxxxxxx y=zzz
Finding VCD file...
./dump.vcd
[2023-07-25 10:57:10 UTC] Opening EPWave...
Done

www.vlsiforall.com
VLSI FOR ALL

Dataflow Modelling
module en_83(output reg [2:0] y, input [7:0]i, input en);

assign y[2]= i[4]|i[5]|i[6]|i[7] &en;


assign y[1]= i[2]|i[3]|i[6]|i[7] &en;
assign y[0]= i[1]|i[3]|i[5]|i[7] &en;
endmodule

Gate Level Modelling VLSI FOR ALL


module en_83(output reg [2:0] y, input [7:0]i, input en);

wire temp1,temp2,temp3; // temp is used to apply


// enable for the or gates
// check the logic diagram and use
// logic gates to compute outputs
or (temp1,i[4],i[5],i[6],i[7]);
or (temp2,i[2],i[3],i[6],i[7]);
or (temp3,i[1],i[3],i[5],i[7]);

www.vlsiforall.com
and (y[2],temp1,en);
and (y[1],temp2,en); VLSI FOR ALL
and (y[0],temp3,en);

endmodule

Structural Modelling

module and_gate(output d,input c,e);


assign d =c & e;
endmodule

module or_gate(output l, input m,n,o,p);


assign l=m|n|o|p;
endmodule

VLSI FOR ALL


module en_83(output reg [2:0] y, input [7:0]i, input en);

wire temp1,temp2,temp3;
or_gate u1(temp1,i[4],i[5],i[6],i[7]);
or_gate u2(temp2,i[2],i[3],i[6],i[7]);
or_gate u3(temp3,i[1],i[3],i[5],i[7]);

and_gate u4(y[2],temp1,en);
and_gate u5(y[1],temp2,en);
and_gate u6(y[0],temp3,en);

www.vlsiforall.com
Que 1) What is Verilog and its primary use?

Verilog is a hardware description language (HDL) used primarily for designing and describing
digital systems.

Verilog allows designers to describe the behavior and structure of digital circuits, which can
be used to synthesize, simulate, and verify hardware designs.

The primary uses of Verilog include:

Hardware Design

Simulation

Synthesis

Verification

Digital System Modeling

Verilog plays a crucial role in the digital design flow, enabling engineers to efficiently design,
simulate, and verify complex digital systems, from small digital components to large
integrated circuits.

Que 2) How do you define a module in Verilog?

module is a fundamental building block used to define a hierarchical entity that represents a
digital circuit

Modules encapsulate the functionality and structure of a circuit, making it easier to design,
simulate, and reuse complex systems.

Ex:

module module_name (list_of_ports);

// Port and data type declarations

input [width-1:0] input_port1;

input [width-1:0] input_port2;

output [width-1:0] output_port1;

// ... other ports ...

// Internal signal declarations

wire [width-1:0] internal_signal1;

reg [width-1:0] internal_signal2;

// Specify the behavior or structure of the module


// using procedural blocks, concurrent assignments, or both.

// Behavioral description using procedural blocks (always, initial, etc.)

always @(posedge clock) begin

// Sequential logic or state updates

internal_signal2 <= input_port1 + input_port2;

end

// Structural description using concurrent assignments or module instances

assign output_port1 = internal_signal1 & internal_signal2;

// ... other behavioral and structural descriptions ...

Endmodule

Que 3) What are the different types of modeling styles in Verilog?

Behavioral Modeling:

Behavioral modeling focuses on describing the functionality and behavior of a digital circuit
at a higher level of abstraction.

Behavioral models use procedural blocks like always , initial , function , and task to specify the
behavior of the design using high-level programming constructs.

Behavioral modeling is commonly used in early design stages, for testbench development,
and for functional verification of the design.

Structural Modeling:

Structural modeling describes a digital circuit by specifying its structure and interconnections
using lower-level components like gates, flip-flops, and other modules.

Structural modeling allows designers to create complex designs by connecting lower-level


modules together, promoting modularity and reusability.

It focuses on how the circuit should be implemented and interconnected.

Dataflow Modeling:

Dataflow modeling is efficient for modeling combinational logic, but it may not be suitable
for representing sequential behavior.
Dataflow models use continuous assignments (assign statements) to express the connections
between input and output signals.

This style is most appropriate for designs where the behavior depends only on the current
input values and not on any clock or timing-related constraints.

It's important to note that Verilog allows a mix of these modeling styles within a
design, and the appropriate choice of modeling style depends on the complexity and
requirements of the circuit being designed.

Behavioral modeling is commonly used for testbenches and high-level design


description,

while structural and dataflow modeling are used for implementing the circuit at a
lower level of abstraction, preparing it for synthesis and hardware realization.

Que 4) How do you specify the size of a signal in Verilog?

In Verilog, We can specify the size of a signal using a range specifier or a bit-width specifier,
depending on whether the signal is a scalar (single bit) or a vector (multiple bits).

Scalar Signal:

A scalar signal is a single-bit signal, and you specify its size using the reg or wire keyword
along with the range specifier

Example :

reg a; // 1-bit signal

wire [7:0] a; // 8-bit signal (7 downto 0)

Vector Signal

A vector signal represents multiple bits, and you specify its size using the reg or wire keyword
along with the bit-width specifier.

Ex:

reg [3:0] a; // 4-bit vector (3 downto 0)

wire [15:0] a;// 16-bit vector (15 downto 0)

Both reg and wire can be used for scalar and vector signals.

Que 5) What are the procedural blocks in Verilog, and how do they differ?

In Verilog, procedural blocks are used to describe the behavior of a digital circuit in response
to events or simulation time changes.

The always block is used to model sequential logic and registers in Verilog.
The initial block is used to model combinational logic and initialize values at the start of the
simulation.

It's important to note that any procedural block (including initial) should not be used for
modeling synchronous logic (clocked logic) as it can lead to simulation mismatches or
synthesis issues.

always blocks are used for modeling sequential logic, and their behavior is sensitive to
specific events or signal changes.

On the other hand, initial blocks are used for modeling combinational logic and execute only
once at the beginning of the simulation.

Que 6) How do you represent time in Verilog simulations?

Verilog provides various time units and precision levels to model simulation time.

Time Units:

Verilog allows you to specify time values using different units, such as seconds, milliseconds,
microseconds, and nanoseconds.

The available time units are:


 s : seconds
 ms : milliseconds
 us : microseconds
 ns : nanoseconds
 ps : picoseconds
 fs : femtoseconds (for high-precision simulations)
Ex:

#10; // 10 time units (default time unit is determined by the simulator)

#100ns; // 100 nanoseconds

#5us; // 5 microseconds

#2ms; // 2 milliseconds

Verilog simulators have a system-wide time unit (usually 1 ns) which can be overridden using
the timescale directive.

Time Precision:

Time precision represents the smallest time unit used for simulation time measurement and
display.

You can specify the time precision using the timescale directive at the beginning of the
Verilog file.

The syntax for the timescale directive is: timescale time_unit/precision_unit .

EX:
`timescale 1ns/100ps // Set time unit to 1 nanosecond and time precision to 100 picoseconds

Delay Statements:

Verilog provides delay statements to control the timing of events in simulations.

Delay statements are specified using # followed by a time value.

Delay statements are commonly used in testbenches to control the sequence of events and
simulation time.

Que 7) What are the different types of delays in Verilog?

In Verilog, there are three main types of delays used to model timing in digital circuits during
simulation.

# Delay:

The delay is specified using a time value after the # symbol, representing a time unit or a
combination of time units and precision.

 This delay is used to model gate delays, propagation delays, and other time-
sensitive behavior in the design.
@ Delay (Event Control):

It specifies that the statement inside the procedural block should execute only when the
specified event occurs.

The event expression can be a combination of signals, edges (posedge/negedge), or other


events.

Transport Delay (#0 Delay):

The transport delay is a special type of delay represented by #0 and indicates zero delay.

It is used to model zero-delay propagation of signals in simulation, particularly in


testbenches.

Que 8) How does Verilog handle signal assignments and concurrent statements?

Continuous Assignments:

Continuous assignments are used to model combinational logic in Verilog.

They are represented using assign statements and describe the direct connections between
input and output signals.

Ex:

module CombinationalLogic(input A, input B, output Y);

assign Y = A & B; // Y is continuously assigned the AND of A and B

endmodule
Procedural Blocks:

Procedural blocks in Verilog (such as always , initial , begin-end , etc.) are used to model
sequential logic.

Procedural blocks contain procedural statements (assignments, conditionals, loops, etc.) that
execute sequentially.

Que 9) What is a sensitivity list in Verilog, and why is it important?

a sensitivity list is a crucial component used to specify the events that trigger the execution
of procedural blocks (such as always and initial )

Edge-Sensitive Sensitivity List:

For edge-sensitive blocks (e.g., triggered by rising or falling edges of a clock)

Ex:

always @(posedge clock) // The block is sensitive to the rising edge of the 'clock' signal

always @(negedge reset_n) // The block is sensitive to the falling edge of the 'reset_n' signal

Level-Sensitive Sensitivity List:

For level-sensitive blocks, you list the signals without specifying any edge type.

always @(a or b) // The block is sensitive to changes in the 'a' or 'b' signals

Importance of Sensitivity List:

Event Triggering:

The sensitivity list defines the events that trigger the execution of procedural blocks.

Avoiding Race Conditions:

Incorrect or incomplete sensitivity lists can lead to race conditions in the simulation.

A race condition occurs when the simulator cannot determine the execution order of blocks
properly, resulting in non-deterministic behavior.

Functional Verification:

Accurate sensitivity lists are essential for functional verification of digital designs.

Que 10) How do you handle race conditions in Verilog designs?

Handling race conditions in Verilog designs is crucial to ensure correct and predictable
behavior during simulation and hardware implementation.

Use Non-blocking Assignments for Flip-Flops:

For sequential logic elements (flip-flops and registers), use non-blocking assignments ( <=)
inside always @(posedge clock) blocks.
Avoid Combinational Cycles:

Combinational loops can lead to race conditions, as changes in signals can propagate
indefinitely without stabilizing.

Proper Sensitivity Lists:

Missing or incorrect sensitivity lists can lead to race conditions and unpredictable behavior.

Be explicit about the signals the block should be sensitive to, and avoid using wildcard
sensitivity (always @(*) ) when possible.

Use Synchronous Resets:

Use synchronous resets for flip-flops to ensure that the reset signal is only applied during a
clock edge.

Ex:

always @(posedge clk) begin

if (reset) begin

// Reset logic

end else begin

// Normal operation

end

end

Use Blocking Assignments for Combinational Logic:

Ex:

always @ (a or b) begin

// Use blocking assignments for combinational logic

c = a & b;

d = ~a;

end

Avoid Mixed Blocking and Non-blocking Assignments:

Avoid mixing blocking and non-blocking assignments for the same signal within the same
procedural block.

Mixed assignments can lead to race conditions and difficult-to-debug simulation behavior.

Que 11) What is a testbench, and why is it essential in hardware design?


A testbench is a critical component in hardware design and verification. It is a separate
module or entity written in a hardware description language (HDL) like Verilog

Functional Verification:

A testbench allows designers to verify the functional correctness of their digital design.

Error Detection and Debugging:

Testbenches help in the early detection and identification of design errors and bugs.

Coverage Analysis:

Testbenches are essential for coverage analysis, which measures the completeness of the
verification process

Corner Case Testing:

Testbenches allow designers to test their designs under various corner cases and extreme
conditions

Performance Evaluation:

Testbenches can be used to evaluate the performance of the design, including timing,
throughput, and latency.

a testbench is an essential tool in hardware design because it facilitates functional


verification, error detection, and debugging.

Que 12) How do you instantiate modules in Verilog?

In Verilog, you can instantiate modules to create hierarchical designs and connect different
modules together to build complex digital circuits

To instantiate a module in Verilog, you use the module_instance syntax.

Ex:

module MyModule(input A, input B, output Y);

// Module implementation here

assign Y = A & B;

endmodule

………………….

To instantiate MyModule and connect it to other signals within your design, you use the
following syntax:

module TopModule(input X, input Z, output Result);


// Instantiate MyModule and connect its ports

MyModule instance_name (.A(X), .B(Z), .Y(Result));

// Other statements and logic for TopModule

Endmodule

Que 13) What is a Verilog parameter, and how is it used?

In Verilog, a parameter is a user-defined constant that can be used to specify values that
remain constant throughout the simulation or synthesis process.

Parameters provide a way to make a design more flexible and configurable, allowing you to
change certain values at the top level of the design without modifying the module's internal
code.

Parameter Declaration:

Parameters are declared within a module using the parameter keyword.

Syntax:

module MyModule #(parameter WIDTH = 8) (input [WIDTH-1:0] data_in, output [WIDTH-1:0]


data_out);

// Module implementation here

Endmodule

Parameter Usage:

They are particularly useful for defining data widths, array sizes, delays, or any other constant
value

Overriding Parameters:

When instantiating a module, you can override the default value of the parameters,
providing a new value based on your specific needs.

Ex:

module mymodule #(parameter width = 8) (input [width-1:0] data_in, output [width-1:0]


data_out);

// module implementation using the width parameter

assign data_out = data_in << 1;


endmodule

……………………..

module topmodule;

parameter my_width = 16;

// instantiate mymodule with custom parameter value

mymodule #(my_width) my_instance (.data_in(input_data), .data_out(output_data));

endmodule

Benefits of Parameters:

Configurability: Parameters make the design more configurable, allowing you to change
specific values at the top level without altering the module's implementation.

Code Reusability: Parameters promote code reusability by enabling the same module to be
used in multiple designs with different configurations.

Maintainability: By centralizing configurable values in parameters, it becomes easier to


manage and modify the design when needed.

Que 14) What is a Verilog task, and how is it different from a function?

In Verilog, tasks and functions are both used to encapsulate reusable code and improve code
organization.

Task:

Tasks are defined using the task keyword, and they can have input and output arguments
similar to functions.

Tasks can contain any procedural statements, including assignments, loops, conditionals, and
delays.

Unlike functions, tasks do not return values directly. Instead, they can modify the values of
their output arguments, which allows them to have multiple outputs.

Tasks are typically used for modeling complex procedural operations, particularly for
testbenches and verification.

Function:

A function in Verilog is a construct used to define a block of procedural code that returns a
single value.

Functions can only contain procedural statements that do not have time delays or blocking
statements (#, wait, etc.).
They are intended for purely combinational logic, and any delays should be handled outside
the function.

Functions are used to model combinational logic, calculate values

Differences between Tasks and Functions:

Return Value: A task does not return a value directly, but it can modify the values of its
output arguments. A function, on the other hand, returns a single value.

Procedural Content: Tasks can contain any procedural statements, including delays and
blocking statements, while functions can only contain combinational logic (no delays).

Multiple Outputs: A task can have multiple output arguments, while a function returns only
a single value.

Usage: Tasks are often used for complex procedural operations in testbenches and
verification, while functions are used for combinational logic modeling and calculations.

Que 15) How do you simulate a clock in Verilog, and why is it necessary?

Simulating a clock is necessary for testing and verifying designs that include sequential logic
elements (such as flip-flops) that depend on clock edges for their operation.

Simulating a Clock:

To simulate a clock in Verilog, you can create a continuous assignment statement that
toggles a signal between 0 and 1 at regular intervals,

Ex:

module Testbench;

reg clock; // Clock signal (1-bit)

// Continuous assignment to generate the clock signal

always #5 clock = ~clock; // Toggle clock every 5 time units

// Rest of the testbench code here

Endmodule

he clock signal is a 1-bit register that is continuously assigned the complement of its current
value every 5 time units, effectively generating a clock signal with a 50% duty cycle (high and
low levels are equal).

Necessity of Simulating a Clock:


Testing Sequential Logic: Sequential logic elements, such as flip-flops, latch, and registers,
depend on clock edges (rising or falling) to update their outputs

Functional Verification: Simulating a clock allows you to verify the correct behavior of your
digital design under different clock frequencies and timing scenarios.

Testbench Generation: In testbenches, generating a clock signal helps control the timing
and sequencing of events.

Coverage Analysis: Clock simulation enables you to perform coverage analysis to check
how well your design is exercised with different clock rates and duty cycles.

Que 16) Explain the concept of hierarchical design in Verilog.

Hierarchical design in Verilog is a design methodology that allows you to break down a
complex digital circuit into smaller parts.

These smaller modules are then interconnected and combined to create the entire system.

The idea behind hierarchical design is to promote modularity, reusability, and ease of design,
verification, and maintenance.

Key Concepts of Hierarchical Design in Verilog:

Module Instantiation:

In Verilog, hierarchical design is achieved through module instantiation. You can instantiate
smaller modules within larger ones to build a hierarchical structure.

Each module acts as a black box, and its internal implementation is hidden from the higher-
level modules, promoting encapsulation.

Module Hierarchy: In a hierarchical design, modules form a hierarchy, where higher-level


modules are built using lower-level modules.

Port Connectivity:

Module instantiation allows you to connect the ports of lower-level modules to signals
within the higher-level module.

This interconnection defines the interaction and communication between modules.

Que 17) How do you model sequential logic in Verilog?

Sequential logic operates on clock edges (rising or falling edges) to transfer data between
registers, enabling the creation of memory elements and state machines

Using Always Blocks:

Verilog provides two types of always blocks for this purpose: always @(posedge clock) for
positive-edge-triggered flip-flops and always @(negedge clock) for negative-edge-triggered
flip-flops.
Using Non-Blocking Assignments:

It is essential to use non-blocking assignments ( <=) for sequential logic modeling to ensure
proper updates in the presence of multiple flip-flops driven by the same clock.

Using Initial Blocks for Reset:

Using Case Statements for Finite State Machines (FSMs):

Que 18) What is a flip-flop, and how is it represented in Verilog?

A flip-flop is a fundamental building block in digital circuits used to store a single bit of
information (0 or 1).

It is a type of sequential logic element that relies on a clock signal to control when data is
transferred and stored.

Flip-flops are commonly used to create memory elements, register data, and implement
state machines in digital designs.

EX: D Flip-Flop Representation:

module dflipflop(input d, input clk, output reg q);

always @(posedge clk)

q <= d;

endmodule

………….

JK Flip-Flop Representation:

module jkflipflop(input j, input k, input clk, output reg q);

always @(posedge clk)

if (j & ~k)

q <= 1'b1;

else if (~j & k)

q <= 1'b0;

endmodule
QUE 19) How do you model combinational logic in Verilog?

In Verilog, combinational logic is modeled using continuous assignments or procedural


blocks inside an always block that are sensitive to the inputs

Continuous Assignments:

Continuous assignments are used for modeling simple combinational logic with direct
connections between inputs and outputs.

module CombinationalLogic(input A, input B, output Y);

assign Y = A & B; // Example of an AND gate

endmodule

Procedural Blocks:

For more complex combinational logic that involves conditionals and arithmetic operations,
you can use procedural blocks inside an always block.

module CombinationalLogic(input A, input B, input C, output reg Y);

always @* begin

// Combinational logic using procedural assignments

if (A & B)

Y = C;

else

Y = ~C;

end

endmodule

Delay Modeling:

Combinational logic is inherently free from delays, but you may also want to model delays in
your design for specific purposes like delay testing or to match real-world behavior.

Delays can be added using the # operator or delay in a procedural block.

module CombinationalLogic(input A, input B, output Y);

// Combinational logic with delay

always @* begin
#10; // Delay of 10 time units

Y = A | B; // Example of an OR gate after a delay of 10 time units

end

endmodule

Combining Continuous Assignments and Procedural Blocks: In complex designs, you


may use a combination of continuous assignments and procedural blocks to model
combinational logic effectively.

Que 20) How do you create a testbench for a Verilog module?

The testbench provides stimulus to the DUT, captures its outputs, and checks whether the
DUT's behavior matches the expected results

Create the DUT Module:

Write the Verilog code for the module you want to test. This is the Design Under Test (DUT)
that you want to verify.

Design the Testbench Module:

Create a new Verilog module that will serve as the testbench. The testbench module
contains the following components:
 Declare and instantiate the DUT module.
 Define input and output signals for stimulus and result capturing.
 Generate clock signal or other stimulus needed for testing.
 Write the procedural code for applying inputs to the DUT and capturing its
outputs.
 Include assertions or checks to verify the correctness of the DUT's outputs.

Que 21) How do you use the "case" statement in Verilog?

The "case" statement in Verilog is used to implement multi-way decision-making or


conditional logic.

Que 22) How do you simulate asynchronous resets in Verilog?

In Verilog, you can simulate asynchronous resets by using the initial or always blocks with
sensitivity to the reset signal

Using initial Blocks:

You can use an initial block to model an asynchronous reset. An initial block executes once at
the beginning of the simulation.

module AsyncResetModule(input reset_n, output reg Q);


// Asynchronous reset using initial block

initial

Q = 1'b0; // Initial value of Q is 0

always @(posedge clk or negedge reset_n)

begin

if (!reset_n) // Asynchronous reset (active low)

Q <= 1'b0; // Reset the flip-flop when reset_n is asserted

else

Q <= D; // Update Q with D on positive clock edge

end

endmodule

Using always Blocks:

You can also use an always block with both the clock and reset signals in the sensitivity list to
model an asynchronous reset.

module AsyncResetModule(input D, input clk, input reset_n, output reg Q);

// Asynchronous reset using always block

always @(posedge clk or negedge reset_n)

begin

if (!reset_n) // Asynchronous reset (active low)

Q <= 1'b0; // Reset the flip-flop when reset_n is asserted

else

Q <= D; // Update Q with D on positive clock edge

end

endmodule
When using asynchronous resets, make sure to handle any potential race conditions or
glitches that may arise due to the asynchronous nature of the reset signal.

Synchronizers or other techniques can be used to safely synchronize the asynchronous reset
signal with the clock domain if needed.

Que 23) What are Verilog event controls, and how do they affect simulation behavior?

Verilog provides three types of event controls:

@ (Posedge Event Control): The @ event control triggers the procedural block when there
is a positive edge transition (rising edge) of the specified signal(s) in the sensitivity list.

@ (Negedge Event Control): Similarly, the @ event control can trigger the procedural block
when there is a negative edge transition (falling edge) of the specified signal(s) in the
sensitivity list.

@* (Combination Event Control): The @* event control triggers the procedural block
whenever any of the signals in the sensitivity list change, regardless of the direction of the
transition.

Be cautious with combination event control ( @*) as it may lead to race conditions or
simulation inefficiencies if not used carefully.

Que 24) How do you create a clock generator module in Verilog?

module ClockGenerator(

input clk_enable, // Input signal to enable/disable the clock generation

input reset_n, // Input signal to asynchronously reset the clock generator

output reg clk // Output clock signal

);

// Define clock parameters

parameter CLOCK_PERIOD = 10; // Time period of the clock (in time units)

parameter DUTY_CYCLE = 0.5; // Duty cycle of the clock (50% by default)

// Clock generation using an always block

always @(posedge reset_n or negedge clk_enable)

begin

if (!reset_n) // Asynchronous reset (active low)

clk <= 1'b0; // Reset the clock to 0


else if (!clk_enable) // Check if the clock generation is disabled

clk <= 1'b0; // Output 0 when the clock is disabled

else

clk <= #CLOCK_PERIOD/2 ~clk; // Generate the clock signal

end

endmodule

frequency and duty cycle of the generated clock are defined by the CLOCK_PERIOD and
DUTY_CYCLE parameters.

Que 25) What is Verilog gate-level modeling, and when is it used?

Verilog gate-level modeling is a type of digital circuit modeling in which the design is
described at the gate level, using primitive logic gates (AND, OR, NOT, etc.) and other basic
gate-level components like flip-flops and multiplexers.

In gate-level modeling, the design is specified in terms of the interconnections between


these gates, representing the physical implementation of the circuit.

Syntax:

module GateLevelExample(input A, input B, input C, output Y);

and gate1(Y, A, B);

or gate2(Y, Y, C);

endmodule

gate-level modeling is commonly used:

Synthesis: After completing the RTL (Register Transfer Level) design, gate-level modeling is
used during the synthesis process

Power and Timing Analysis: Gate-level modeling is essential for power and timing analysis
to understand the circuit's performance and power consumption at the physical level.

Gate-Level Simulation: Gate-level models can be used for gate-level simulation, where the
behavior of the design is verified at the gate level rather than the higher-level RTL.

Que 26) How do you use delays in Verilog testbenches to model real-world behavior?

Use

Propagation Delays:

Introduce propagation delays in signal assignments to model the time it takes for a signal to
propagate through combinational logic or wires.
You can use the # operator to specify the delay in time units.

EX:

module Testbench;

reg input_signal;

wire output_signal;

// Propagation delay in signal assignment

always @* begin

#5 output_signal = input_signal; // Introduce a 5-time unit propagation delay

end

// ... Rest of the testbench ...

Endmodule

………….

Clock Period: When generating a clock signal in the testbench, specify the clock period to
simulate the clock's real-world frequency.

EX:

module Testbench;

reg clk;

// Clock generation with a specified clock period

initial begin

clk = 0;

forever #10 clk = ~clk; // Generates a 50% duty cycle clock with 10 time units period

end

// ... Rest of the testbench ...

Endmodule

Input Timing:
EX:

module Testbench;

reg input_signal;

// Delay between input changes

initial begin

#20 input_signal = 1;

#30 input_signal = 0;

#100 $finish; // End simulation after 100 time units

end

// ... Rest of the testbench ...

Endmodule

Output Timing: When checking outputs, consider modeling the delay required to settle the
output response after applying inputs.

EX:

module Testbench;

reg input_signal;

wire output_signal;

// Apply inputs and wait for output response

initial begin

input_signal = 1;

#50; // Wait for 50 time units for output to settle

$display("Output: %b", output_signal);

$finish;

end

// ... Rest of the testbench ...


Endmodule

Clock Skew and Jitter:

To model clock skew or jitter, you can introduce random delays or jitter components in clock
generation.

Que 27) What is a Verilog net, and how is it different from a register?

In Verilog, a "net" and a "register" are two distinct types of hardware elements used to
represent and model different aspects of a digital design.

Net:

A net in Verilog represents a continuous signal that connects various elements within the
design.

It is used to model the interconnections between gates, flip-flops, and other logic elements.

Nets are used for representing the interconnecting wires in a circuit and do not have any
state or storage capability.

They are mainly used to model combinational logic and the propagation of signals through
the design.

EX:

module MyModule(input A, input B, output Y);

wire net1, net2; // Declaration of nets

and gate1(net1, A, B);

or gate2(Y, net1, net2);

endmodule

Register:

A register in Verilog represents a sequential element that can store and retain data over time.

It is used to model memory elements like flip-flops or registers in a digital design.

Registers have state, which means they can store information and hold their value between
clock cycles.

Registers are declared using the reg keyword in Verilog.

EX:

module MyModule(input clk, input D, output reg Q);

always @(posedge clk) begin


Q <= D; // Register storing the value of D on the rising edge of clk

end

endmodule

the key difference between a net and a register in Verilog is that a net represents a
continuous signal used for interconnections and propagation of values in combinational
logic,

while a register represents a sequential storage element that holds data and has state,
commonly used in sequential logic and finite state machines.

Que 28) How do you handle X and Z states in Verilog simulations?

In Verilog simulations, "X" and "Z" are special states that represent unknown and high-
impedance (floating) values, respectively.

These states can occur during simulation due to various reasons, such as uninitialized
variables, undriven nets, or undefined behavior in the design.

Initialize Variables: Ensure that all variables, including registers and memories, are properly
initialized before they are used in the design.

Avoid Combinational Loops: Be cautious of combinational loops in your design, as they


can result in undetermined logic states (e.g., "X" values). Design your logic to avoid feedback
paths that can lead to race conditions.

Use Proper Testbench Stimuli: Ensure that your testbench provides appropriate stimuli to
exercise the design properly. Avoid invalid or unknown input values that could lead to "X"
states in the design.

Check for "X" and "Z" States: Monitor your simulation results for "X" and "Z" values. You
can use $display or $monitor statements to print out the values

Que 29) Explain the difference between procedural continuous assignments and
concurrent continuous assignments in Verilog.

continuous assignments are used to model combinational logic and provide a way to assign
values to nets continuously, without the need for a procedural block.

There are two types of continuous assignments in Verilog: procedural continuous


assignments and concurrent continuous assignments.

Procedural Continuous Assignments:

Procedural continuous assignments are defined within procedural blocks, such as initial ,
always , or task blocks.
Procedural continuous assignments use the blocking assignment ( =) operator to make the
assignment.

Example of Procedural Continuous Assignment:

module ProceduralContinuousAssignment(input A, input B, output Y);

reg net1; // Declare a net

// Procedural block with continuous assignment

always @* begin

net1 = A & B; // Procedural continuous assignment using blocking assignment

end

assign Y = net1; // Concurrent continuous assignment

endmodule

Concurrent Continuous Assignments:

Concurrent continuous assignments are defined outside procedural blocks, directly within
the module's scope.

They are used to continuously assign values to nets based on combinational expressions
using the assign keyword.

Concurrent continuous assignments use the non-blocking assignment ( <=) operator to make
the assignment.

Example of Concurrent Continuous Assignment:

module ConcurrentContinuousAssignment(input A, input B, output Y);

wire net1; // Declare a net

assign net1 = A & B; // Concurrent continuous assignment using non-blocking assignment

assign Y = net1; // Another concurrent continuous assignment

endmodule

Que 30) How do you use the "fork" and "join" statements in Verilog?

In Verilog, the fork and join statements are used to create concurrent execution blocks. These
statements allow multiple tasks or blocks of procedural code to run concurrently in a
simulation.

fork
// Concurrent blocks or tasks

// ...

Join

The fork statement is used to start concurrent execution, and the join statement is used to
synchronize the execution and wait for all concurrently running blocks to finish before
proceeding with the simulation

Using the fork and join statements can be helpful in creating more complex and realistic
testbenches, especially when you want to simulate multiple tasks or events concurrently.

However, be careful to avoid race conditions or unintended interactions between concurrent


blocks, as they can lead to unexpected simulation behavior.

Que 31) What are the implications of simulation time and real time in Verilog?

In Verilog simulation, there are two types of time systems: simulation time and real time.

Simulation Time:

Simulation time is the time used internally by the Verilog simulator to schedule and execute
events and simulate the behavior of the design.

No Real-Time Behavior: Simulation time does not represent real-world time directly. It can be
faster or slower than real time, depending on the design's complexity and the simulator's
performance.

It is discrete and is measured in time units specified using the # operator in Verilog.

Real Time:

It is continuous and is measured in real-world units like seconds, milliseconds, etc.

Real time is used for time-based simulation control and analysis of the simulation's duration
in real-world terms.

Combining Simulation Time and Real Time:

The $time system function provides the current simulation time (in time units), while the
$realtime system function provides the current real time (in real-world units).

The $timeformat system task allows you to set the format for displaying simulation time.

The $stime system task allows you to set the simulation time explicitly.

Simulation time can be controlled using delays (#) and timers, while real time is used for
monitoring the overall simulation duration and performance.

Que 32) How do you create parameterized Verilog modules?

To create parameterized Verilog modules, you need to use the parameter keyword to declare
the parameters and then use them in the module's logic.
Step 1: Declare Parameters:

Start by declaring the parameters inside the module definition using the parameter keyword.
Parameters act like constants and can be of any data type.

Step 2: Use Parameters in Logic:

module MyParameterizedModule #(parameter WIDTH = 8, parameter ENABLE = 1'b1) (

input [WIDTH-1:0] data_in,

output [WIDTH-1:0] data_out

);

// Logic using the parameters

reg [WIDTH-1:0] internal_reg;

always @(posedge clk) begin

if (ENABLE)

internal_reg <= data_in;

end

assign data_out = internal_reg;

endmodule

Step 3: Instantiate the Parameterized Module:

module MyTopModule;

// Parameterized module instantiation with custom parameter values

MyParameterizedModule #(WIDTH=16, ENABLE=1'b0) my_instance (

.data_in(input_data),

.data_out(output_data)

);

// Other module logic

// ...

Endmodule

Que 33) How do you handle floating-point arithmetic in Verilog?


Verilog, as a hardware description language, is primarily designed for digital logic modeling
and does not have built-in support for floating-point arithmetic like software programming
languages (e.g., C, C++, Python). However, there are ways to model floating-point arithmetic
in Verilog using fixed-point representation or by using external floating-point IP cores.

Fixed-Point Representation:

One common approach to handle floating-point arithmetic in Verilog is by using fixed-point


representation. In fixed-point representation, real numbers are represented as integers, and
the radix point is implicitly placed at a specific position to define the fractional part.

This approach allows you to perform basic floating-point operations using integer arithmetic.

module FixedPointArithmetic;

reg signed [7:0] fixed_a;

reg signed [7:0] fixed_b;

wire signed [7:0] fixed_result;

// Assign values to fixed-point numbers

initial begin

fixed_a = 8'b00110010; // 3.5 in fixed-point representation

fixed_b = 8'b00010100; // 1.25 in fixed-point representation

// Perform addition

fixed_result = fixed_a + fixed_b;

$display("Result: %f", fixed_result);

end

endmodule

SystemVerilog Floating-Point Data Types (for Verification): If you are using


SystemVerilog for verification (testbenches), SystemVerilog does provide built-in support for
floating-point data types (real and realtime) and floating-point arithmetic.

Que 34) How do you handle initial values for registers in Verilog?

There are two ways to handle initial values for registers in Verilog:

Using Blocking Assignments: You can use blocking assignments ( =) inside an initial block to
assign an initial value to a register.
Using Non-Blocking Assignments (Recommended for Synthesizable Code): When
writing synthesizable Verilog code, it is recommended to use non-blocking assignments ( <=)
instead of blocking assignments for register initialization.
Linkedin_orsuvenkatakrishnaiah
Linkedin_orsuvenkatakrishnaiah
1.what logic is inferred when there are multiple assign statements targeting the same wire?
It’s not possible to specify multiple assign statements to the same wire in a Synthesizable code that will
become an output port of the module. The Synthesis tools give a syntax error that a net is being driven by
more than One source.
For an example:-
module multi_wire(input in1,in2,output temp);

assign temp=in1&in2;
assign temp=in1|in2;
endmodule

Note:-Only one type of output assignment is legal for synthesis


Linkedin_orsuvenkatakrishnaiah

2.what do conditional assignments get inferred into?

• conditionals in a continuous assignment are specified through the “?:” operator. conditionals get inferred
into a multiplexor.

• for an example
module example2(input sel,a,b,output wire wire1);

assign wire1=(sel)?a:b;

endmodule
Linkedin_orsuvenkatakrishnaiah
3.what is the logic that gets synthesized when conditional operators in a single continuous assignment are
nested?

• The logic gets elaborated into a tree of multiplexors.


• for an example
module example3(input sel1,sel2,sel3,a,b,c,d,output out1);

assign out1=(sel1)?a:sel2?b:sel3?c:d;

endmodule
Linkedin_orsuvenkatakrishnaiah
4. what value is inferred when multiple procedural assignments made to the same reg variable in an always
block?
• when there are multiple nonblocking assignments made to the same reg variable in a sequential always block, then the last assignment is picked up
for logic synthesis.
• for an example
module example4(input clk,a,b,output out2);
reg temp;
always@(posedge clk)begin
temp<=a^b;
temp<=a|b;
temp<=a&b;
end
assign out2=temp;
endmodule
Linkedin_orsuvenkatakrishnaiah
5.why should a nonblocking assignment be used for sequential logic, and what would happen if a blocking
assignment were used?
• In Verilog, nonblocking assignments (<=) should be used for sequential logic because they allow for
concurrent execution of multiple assignments within the same always block, which is necessary for correct
behavior of sequential circuits.
• If a blocking assignment (=) were used instead of a nonblocking assignment in a sequential always block, it
would cause a race condition where the order of execution of the assignments would be determined by the
order of the statements in the always block. This can lead to unpredictable behavior and incorrect results in
the circuit.
• In a sequential always block, the output signals are usually dependent on the current state of the circuit
and the inputs. Nonblocking assignments allow for the output signals to be updated independently of the
order of the statements in the always block and ensure that the output signals are updated consistently
with the current state of the circuit.
Linkedin_orsuvenkatakrishnaiah
6.Compare above question with the same code in a combinatorial block.

• In a combinatorial block, blocking assignments (=) are typically used to assign values to the output signals because
the outputs are updated directly from the inputs without any clock or state dependencies.
• In a combinatorial block, the order of execution of the statements is not important, as all the statements are
evaluated simultaneously. Therefore, there is no risk of race conditions that can occur with blocking assignments
in a sequential block.
• If a nonblocking assignment (<=) were used in a combinatorial block, it would not necessarily cause any issues or
errors, but it would be unnecessary and could potentially confuse other designers who are reviewing or modifying
the code.
• Overall, the use of blocking assignments in a combinatorial block is appropriate and preferred because it reflects
the nature of the combinatorial logic and avoids any confusion or unnecessary complexity. In contrast,
nonblocking assignments are typically used in sequential blocks to ensure correct behavior and avoid race
conditions.
7. what are the differences between continuous and procedural assignments?
• Continous Assignments
Linkedin_orsuvenkatakrishnaiah
• Assigns values primarily to nets
• Variables and nets Continuosly drive values onto ports
• Used to infer Combinational logic
• Assignment occurs whenever the value on the RHS of the expression changes as a continuous
process
• Occurs in assignments to wire,port and net type.
• For an example
module example5(input in1,in2,output out1);
assign out1=in1&in2;
endmodule
Linkedin_orsuvenkatakrishnaiah
• Procedural Assignments
• Assigns values primarily to Reg variables
• Variables and nets can stores into variables
• Used to infer both storage elements like Sequential logic circuits and Combinational logic
• The value of the previous assignment is held until another assignment is made to the variable.
• Occurs in constructs like always,initial,task and function
• For an example
module example51(input clk,in1,output reg reg1);
always @(posedge clk)
reg1<=in1;
endmodule
8.What are the differences between assignments in initial and always constructs?
Linkedin_orsuvenkatakrishnaiah
• In Verilog, `initial` and `always` constructs are used to specify the behavior of the circuit.
• The main differences between assignments in `initial` and `always` constructs are:
• 1. Timing:
• - The `initial` block is executed only once at the beginning of simulation time, while the `always` block is executed continuously based on the
sensitivity list or trigger event.
• - The `initial` block is used to initialize the circuit's variables and registers with specific values at the start of simulation, while the `always` block is
used to describe the behavior of the circuit during its operation.
• 2. Sensitivity list or trigger event:
• - The `always` block may have a sensitivity list or a trigger event that specifies when the block should be executed. The sensitivity list or trigger event
indicates the changes in input signals that should cause the block to be executed.
• - In contrast, the `initial` block does not have a sensitivity list or trigger event as it is executed only once at the beginning of simulation time.
• 3. Blocking and Nonblocking assignments:
• - Nonblocking assignments (`<=`) are typically used in `always` blocks to ensure correct behavior of sequential logic and avoid race conditions.
• - In `initial` blocks, blocking assignments (`=`) are usually used to initialize variables and registers with specific values at the start of simulation.
9.What are the differences between blocking and nonblocking assignments?
• In Verilog, there are two types of assignments: blocking (`=`) and nonblocking (`<=`) assignments. The main differences between them are:
• 1. Order of execution:
Linkedin_orsuvenkatakrishnaiah
• - Blocking assignments are executed in the order they appear in the code. Once a blocking assignment is executed, the next assignment
can be executed.
• - Nonblocking assignments, on the other hand, are executed concurrently, regardless of their order in the code. All nonblocking
assignments in an always block are executed simultaneously, and the order in which they appear in the code does not matter.
• 2. Timing control:
• - In a combinational logic block, blocking assignments are used to assign values to the output signals as the output values are updated
immediately based on the input signals.
• - In a sequential logic block, nonblocking assignments are used to update the state of the circuit's registers, as the output values depend
on the current state of the circuit and the input signals. Nonblocking assignments ensure that the state of the circuit is updated
consistently with the current state.
• 3. Behavior in simulation:
• - In a simulation, blocking assignments cause a delay in the execution of the next statement, which can cause a time-consuming
simulation.
• - Nonblocking assignments do not cause delays in the execution of subsequent statements, and therefore, they are more efficient in
simulation.
10.How can I model a bi-directional net with assignments influencing both source and destination?

Linkedin_orsuvenkatakrishnaiah

• The assign statement constitutes a continuous assignment. The changes On the RHS of the
statement immediately reflect on the LHS net. However,Any changes on the LHS don't get
reflected on the RHS.

• For example, changes to the rhs net will update the lhs net, but not Vice versa.
wire lhs,rhs;

assign lhs=rhs;

You might also like