Verilog Book
Verilog Book
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
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.
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.
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.
2. Lexical Tokens
Verilog source text files consists of the following lexical tokens:
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.
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.
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. */
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);
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
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.
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 ... ;
Syntax Example 4 .5
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
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
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)
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
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)
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)
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] */
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}}
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 */
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
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.
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
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
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 .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. */
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.
Modules may not be instantiated inside procedural blocks. See “Procedures: Always and Initial Blocks” on page 18.
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.
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.
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.
Syntax Example 8 .5
Syntax Example 8 .6
Syntax Example 8 .7
Syntax Example 8 .9
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
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.
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.
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
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.
Syntax 1 Example 10 .1
Syntax 2
Syntax Example 10 .2
initial inital
begin begin
... statements ... clr = 0; // variables initialized at
end clk = 1; // beginning of the simulation
end
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.
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
Syntax Example 12 .1
Syntax Example 13 .1
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.
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;
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
When modeling finite state machines, it is recommended to separate the sequential current-state logic from the com-
binational next-state and output logic.
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;
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.
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;
Syntax Example 15 .2
Syntax Example 15 .3
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.4. $deposit
$deposit sets a net to a particular value.
Syntax Example 16 .2
16.6. $list
$list (hierarchical_name) lists line-numbered source code of the named module, task, function or named-block.
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.
Syntax Example 16 .4
Syntax Example 16 .5
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);
endmodule
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.
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.
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.
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.
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;
...
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
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.
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:
• 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:
Parameter
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;
And the following code will assign a value to the lower 8 bits of the bus:
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"
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];
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
4. Real – 0.0
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:
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.
Sol: yes, Ports, also referred to as pins or terminals, are used when wiring the module to other
modules.
Sol: gate level, this is the lowest level of abstraction. Here the circuit is described by logical links and
their timing properties
Page | 8
YASWANTH B
8/12/23
DAY-2
8.What is PLI?
Sol: It is the Programming Language Interface used for enabling C programming in Verilog. It
performs multiple tasks
• Passing data
Page | 9
YASWANTH B
8/12/23
DAY-2
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.
// Task body...
endtask
// Function body...
return value;
endfunction
Example:
module AutomaticExample;
count = count + 1;
$display("Task Call %d: Count = %d", $time, count);
endtask
initial begin
integer result;
Que 2) What are the different ways to assign values to an array in Verilog?
array_name[index] = value;
Example:
This method is used to assign values to all elements of an array in a single line.
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
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.
Void Task
Void Function
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?
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:
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.
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.
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;
initial begin
end
endmodule
Signed Arithmetic:
Data Types: Use reg signed or wire signed to represent signed values.
Rules: Signed arithmetic automatically takes care of sign extension and two's complement
representation.
Ex:
module SignedArithmeticExample;
initial begin
end
endmodule
Ex:
Endmodule
Syntax:
endfunction
Example:
module ArrayFunctionExample;
int i;
int sum = 0;
end
return sum;
endfunction
integer result;
initial begin
result = sum_array_elements(my_array);
end
endmodule
genvar is a special variable used in generate blocks (generate /endgenerate ) to control loop
constructs, such as for and foreach loops,
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)
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
Verilog datatypes define the type and size of variables, allowing proper storage and
manipulation of data.
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
he "reg" data type, on the other hand, can store values and simulate sequential behavior.
end
endmodule
Que 3) How do you define a variable of the integer data type 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.
In Verilog, we can declare a 2-dimensional array using the syntax: data_type array_name
[rows][columns];
module TwoDimensionalArrayExample;
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
end
endmodule
module ParameterExample;
initial begin
data = SIZE;
end
endmodule
………………..
module LocalparamExample;
initial begin
signal = WIDTH;
@shraddha_pawankar Date 28/08/23
end
endmodule
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 #(
)(
);
end
endmodule
The "localparam" keyword in Verilog is used to declare constant values that are local to a
module or a specific block of code.
module LocalparamExample;
end
endmodule
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.
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;
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 [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
end
endmodule
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;
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;
assign sum1 = a + b; // 'a' and 'b' are 4-bit, result is automatically 5-bit
assign sum2 = $signed(a) + $signed(b); // Cast 'a' and 'b' to signed 5-bit and then add
assign sum3 = $unsigned(a) + $unsigned(b); // Cast 'a' and 'b' to unsigned 5-bit and then add
initial begin
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).
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
);
assign w1 = a & b;
assign w2 = ~w1;
y <= 1'b0;
else
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.
Verilog provides several casting operators to convert between different data types, such as
$signed , $unsigned , and the curly braces {} for concatenation.
module CastingExample;
initial begin
signed_data = $signed(unsigned_data) - 5;
end
endmodule
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.
initial begin
end
initial begin
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,
initial begin
end
initial begin
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;
initial begin
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?
The correct way to define custom data types in Verilog is to use the typedef keyword.
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
initial begin
packed_array[0] = 8'b10101010;
packed_array[1] = 8'b11001100;
packed_array[2] = 8'b11110000;
packed_array[3] = 8'b00110011;
end
endmodule
A constant array is an array whose values cannot be changed or modified during simulation.
It allows you to create read-only arrays,
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 .
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
-----------
module MultidimensionalArrayExample;
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;
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;
-------------------------------------------------------------------------------------------------------------------------------------
ARRAYS IN VERILOG
MEMORIES
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:
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.
Ex:
Que 3) Describe the process of initializing a Verilog array with specific values.
Que 4) Write Verilog code to implement a 2D unpacked array of 4x4 2-bit elements.
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
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
my_array[i] =$urandom;
end
EX:
module tb;
reg [5:0] a; //packed array
reg b [0:4]; //unpacked array
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.
module mux(in,sel,out);
input sel;
input [1:0]in;
output out;
>> (Divide by 2)
<< (Multiply by 2)
>>>
<<<
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,
Que 3) Can you describe the importance of handling overflow and underflow in
arithmetic shifts?
@shraddha_pawankar date:26/07/23
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.
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.
Que 9) How can logical shifts be used to perform division of unsigned numbers?
Que 10) Explain how logical shifts can be used in bit manipulation to set, clear, or
toggle specific bits.
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:
endmodule
-----------------------------------------------------------------------------------------------------------------------------------
Que 14) Write a Verilog code to perform a logical right shift on an input data bus.
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.
Que 17) How can you optimize the implementation of a shift operation for high-
performance systems?
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 ==
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
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.
always @*
out = (a == b);
endmodule
Que 2) How do you handle "don't care" conditions in Verilog when using case equality?
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:
module IncorrectAlwaysBlockExample(input [1:0] sel, input [3:0] data, output reg [3:0] result);
@shraddha_pawankar Date:27/07/23
endcase
endmodule
module CorrectAlwaysBlockExample(input [1:0] sel, input [3:0] data, output reg [3:0] result);
case(sel)
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
always @*
casex(data)
endcase
endmodule
always @*
casez(data)
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 constructs are primarily used for pattern matching and handling "don't care"
conditions in the input.
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:
always @*
casez(data)
endcase
endmodule
the casez construct considers the sign bit as a regular bit, and it will perform pattern
matching based on its value.
always @*
case(data)
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.
module ProceduralAssignmentExample(input [1:0] sel, input [3:0] data, output reg [3:0]
result);
always @*
casez(sel)
endcase
endmodule
Continuous Assignments:
@shraddha_pawankar Date:27/07/23
module ContinuousAssignmentExample(input [1:0] sel, input [3:0] data, output reg [3:0]
result);
default: 4'b1111;
endcase
endmodule
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:
always @*
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.
Flexibility
Readability
Ease of Modification
always @*
begin
if (sel == 2'b00)
data_out = 4'b0000;
data_out = 4'b0001;
data_out = 4'b0010;
data_out = 4'b0011;
else
@shraddha_pawankar Date:27/07/23
end
endmodule
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.
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.
always @*
casez(sel)
endcase
endmodule
Limited Complexity
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.
always @*
casez(sel)
endcase
endmodule
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.
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
(=== ).
The logical equality operator (==) is used for comparing scalar and vector data types.
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:
always @*
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.
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:
always @*
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
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)
endcase
endmodule
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.
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)
endcase
endmodule
Que 15) How do you handle "don't care" conditions in case equality when dealing with
asynchronous inputs?
Example:
begin
casez(D)
endcase
end
endmodule
Inside the case equality construct, we handle "don't care" conditions by using the "x"
wildcard.
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
1) Always block
2) Initial block
INITIAL BLOCK
----------------------------------------------------------------------------------------------------------
ALWAYS BLOCK
Example :
module half_adder(a,b,sum,carry);
input a,b;
always@(a or b)
begin
sum = a+b;
carry= a&b;
end
endmodule
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:
Example:
always@(posedge clk)
if(sel)
output <= x;
else
output <= y;
output:
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.
-----------------------------------------------------------------------------------------------------------------
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.
if(a>b)
if(a<b)
if(a==b)
endfunction
initial
begin
compare(10,5);
compare(10,10);
compare(3,4);
end
endmodule
https://www.edaplayground.com/x/G7ie
int x;
endfunction
initial
begin
x= sum(3,4);
end
endmodule
https://www.edaplayground.com/x/j7ex
If the function name is used outside the function, the name indicates the scope of the whole function.
module tb;
int x;
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
module tb;
return a+b;
endfunction
initial
begin
$display("calling function");
void'(sum(2,3));
end
endmodule
https://www.edaplayground.com/x/ZPzJ
-------------------------------------------------------------------------------------------------------------------------------------
SYSTEM TASKS
$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 2) Explain the syntax of $display and its basic format specifiers.
Syntax:
$display(“Format specifier”,arguments);
$time and $stime is a system function that can be used with $display to display simulation
time.
Que 8) How do you use $display to print system task names dynamically?
Que 9) Explain the role of $urandom and $urandom_range with $display for random
stimulus generation.
Que 2) How do you use $monitor to monitor signal values during simulation?
Que 4) How can you use $monitor to observe clock and reset signals?
Ex:
Que 6) Discuss the usage of $monitor for debugging FSMs (Finite State Machines).
Que 7) Can you use $monitor for monitoring signals across different clock domains?
Que 8) Explain the usage of $monitor for power analysis and optimization in Verilog
designs.
Que 9) How do you use $monitor for error checking and diagnostics during
simulations?
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?
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.
$monitor is valuable for debugging race conditions in the design by continuously monitoring
signals involved in the potential race.
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:
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
TASK SYNTAX:
task <task_name> (input <port_list>, inout <port_list>, output
<port_list>);
...
endtask
Example:
module add ( clk,din,dout);
input clk;
integer i;
always@(posedge clk)
begin
dout = 0;
for(i=0;i<5;i=i+1)
begin
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;
integer I;
always@(posedge clk)
begin
if(rst)
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?
-------------------------------------------------------------------------------------------------
FOREACH LOOP
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;
'{'{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
https://www.edaplayground.com/x/vqLi
Que 1) How can you ensure that a "forever loop" does not create an infinite simulation
in Verilog?
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?
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
Always:
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?
Q.3) How do you control the execution of a repeat loop in Verilog? How many times
will the loop iterate?
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?
------------------------------------------------------------------------------------------------------
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.
---------------------------------------------------------------------------------------------------------------------
---
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
initial
begin
count=0;
do
begin
$display("count=%0d",count);
count++;
end
while(count<10);
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?
Que2) How do you control the execution of a while loop in verilog? What
condition should be met to terminate the loop?
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
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
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
The timescale setting is fixed once specified at the beginning of the Verilog file and
remains constant throughout the simulation.
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;
initial begin
a1.a=12;
a1.b=3;
$display("Value of addition : %0d",a1.a+a1.b);
end
endmodule
https://edaplayground.com/x/bSkc
---------------------------------------------------------------------------
// Method is written by user in structure
CLASS
class add;
reg [3:0] a;
reg [3:0] b;
reg [4:0] result;
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
https://edaplayground.com/x/hw7F
reg [3:0] a;
reg [3:0] b;
endfunction
task add_two();
result=a+b;
endtask
endclass
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
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()
T=1/f
T=62.5ns
T/2=31.25ns
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;
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;
initial begin
$dumpfile("dump.vcd");
$dumpvars();
end
initial begin
#200
$finish();
end
endmodule
https://edaplayground.com/x/LMAE
module tb;
reg 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.
module binary_to_gray(B,G);
input [3:0] B;
output [3:0] G;
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;
endmodule
https://www.edaplayground.com/x/Znh3
Binary to 2’s Complement Code Converter
module bin_complement_2s(in,out);
endmodule
https://www.edaplayground.com/x/KDfc
BCD to EXCESS-3 CODE Converter
module bcd_excess3(B,Ex_3);
always@(*)
begin
case(B)
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.
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
T Qn+1
0 Qn
1 ~Qn
Code:
module t_ff(clk,rst,t,q);
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);
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);
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
module mux(a,b,s,y);
input a,b,s;
output reg y;
always @(a,b,s)
begin
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
S0
00 S1
Clk_2=1 Clk_2=0
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
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;
//-------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
S0
Clk_1 = 1 S1
clk_2=1 Clk_1 = 0
clk_2=0
S2
Clk_1 = 0
clk_2=0
reg clk_1,clk_2;
parameter s0=2'b00,s1=2'b01,s2=2'b10;
@shraddha_pawankar Date: 1/8/2023
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
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
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.
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.
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
Program:
module clock_edge(clk,d_clk,posedge_detect,negedge_detect);
https://edaplayground.com/x/HcXt
--------------------------------------------------------------------------------------------------------------------------------------
CLOCK BUFFER
It is an Jitter Attenuator
Program
module clock_buffer(clk_in,clk_out);
input clk_in;
@shraddha_pawankar Date:31/07/23
output clk_out;
https://www.edaplayground.com/x/CKbM
@shraddha_pawankar Date : 29/07/2023
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.
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
C) Condition coverage:
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
D) Expression coverage
The metric for expression coverage is the count of activity of expression on the RHS
of assignment statement.
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
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.
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
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.
)
Difference between Verilog and
SystemVerilog (in terms of Verification):
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;
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 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;
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->
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
• 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.
• Mode
❖ 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-------------------------
logic [3:0]datain;
logic [3:0]dataout;
logic rst;
logic load;
logic mode;
output rst;
output datain;
output load;
output mode;
endclocking
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;
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;
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
//------------------Write monitor--------------------
class write_monitor;
virtual count_if.wr_mon wr_mon_if;
trans wr_data;
trans data2rm;
mailbox #(trans)mon2rm;
endclass
//----------------------------------Read monitor--------------------
class read_monitor;
virtual count_if.rd_mon rdmon_if;
trans data2sb;
trans rd_data;
endclass
//--------------------Reference Model--------------------------
class count_model;
trans w_data;
static logic [3:0] ref_count=0;
endclass
//-----------------------------ScoreBoard-------------------------
class count_sb;
event DONE;
trans sb_data;
trans rm_data;
trans cov_data;
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
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
endclass
//--------------------Environment-----------------------
class con_env;
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;
//-----------------------Test cases--------------------------------
class test;
con_env env;
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
module tb;
reg[2:0] a;
initial
begin
$display("Display : =%0d",a);
a=3;
$strobe("Strobe = %0d",a);
end
endmodule
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
`timescle 1ns/1ns
#2.3 clk=0;
#1.4 clk=1;
initial begin
a=0;
a<=1;
$display("value of a=%b",a);
End
…………………….
module test;
reg clk;
reg reset;
reg a;
end
initial begin
clk = 0;
reset = 0;
a = 0;
a = 0;
@(posedge clk or negedge reset) // Wait for another clock posedge or reset negedge
a <= 1;
// End simulation
$finish;
end
endmodule
https://edaplayground.com/x/QTiQ
module tb;
$display("%0s",a1);
endmodule
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 .
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 = #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.
Iteration ends
reg [3:0] a;
$display(a);
Explaination:
………………
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.
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 .
always@(posedge clk,reset)
begin
if(reset==1)
q <=0;
else
q<= clk;
end
if (reset == 1)
q <= 0;
else
q <= clk;
end
Que 10) why is it "if(2'b01 & 2'b10)" doesnt run the true case
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.
reg[4:0] a;
a[2:1]=2'b1x;
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
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
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
end
endmodule
So, in the provided code snippet, c gets the value 1 at simulation time 40 .
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 :
consider Snippet 2:
initial
begin
a <= #1 1'b1;
b <= #2 1'b0;
c <= #4 1'b1;
end
Output:
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.
This means that you cannot predict with certainty which initial block will execute first.
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.
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.
Correct syntax:
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)
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
110X
1100
…………
reg[3:0]a=4'b0100;
reg[3:0]b;
initial
begin
b=a+1'bx;
end
Output : 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
reg[3:0] a;
reg[1:0] x;
initial
@shraddha_pawankar 9/8/23
begin
a=4'd10;
x=(a>>1);
end
reg[3:0] a;
reg[6:0] b;
initial
begin
a=4'd10;
b={a,1} //b=7bit
end
b=7’b000_0001
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;
reg[2:0] a;
reg[2:0] x;
initial
begin
a=3'd4;
x=^a;
end
(4)d=100=1^0^0=1
reg[2:0]a,b;
reg y;
initial
begin
a=3'd5;
b=3'b111;
y=a&&b;
end
@shraddha_pawankar 9/8/23
reg[5:0]y;
initial
begin
y='0x2;
end
y is total 6 bit
y=6’bxxx_010
integer b;
initial
begin
b=-'d12/3;
end
2^32-12/3=1431655
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)
reg[3:0] var1;
initial
begin
var1=-5;
$display(var);
End
5=0101
Display=(11)d
initial clk=0;
always@(clk) clk=~clk;
clk=X;
clk=0;
initial clk=0;
always@(clk) clk<=~clk;
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
input C,din;
reg y1,y2;
always@(posedge c)
begin
y1=din;
y2=y1;
y3=y2;
end
input C,din;
reg y1,y2;
always@(posedge c)
@shraddha_pawankar 9/8/23
begin
y1<=din;
y2<=y1;
y3<=y2;
end
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
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
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
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
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
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
A=3 b=2;
reg clock;
initial
begin
#10 clock=0;
end
always@clock;
clock=#10 ~clock
Blocking assignment used within the always process cant trigger active event
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
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
initial
begin : A1
#10;
#20;
#40;
end
initial
fork : A2
#10;
@shraddha_pawankar 9/8/23
#20;
#40;
Join
At 40 time unit : A2 Fork – join -parallel block -delays are non additive
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 never exists,the fork join block also never exists.
@shraddha_pawankar 9/8/23
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;
reg clk;
always
begin
clk=~clk;
end
The value b is evaluated at the current simulation time but not ssigned to out until
after 8 clock cycles
always@(posedge clk)
begin
x<=x<<1;
x[0]<=x[7];
end
x<= x<<1
@shraddha_pawankar 9/8/23
10101101
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
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;
// if c is an output
// -----------------------------
output c;
reg a,b;
assign c = a & b;
// 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
sel
2’b10 2’b11
2
= =
c 0
0
b 1 d
1
a
// 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
c 2’b0x
b 2’b10 d
a 2’b11
enable
d[3:0]
c[3:0]
4
4
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]
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}};
// 2. using a reg
reg d;
always @ (a or c)
d = (a == c);
a[3:0]
4
= 1
d
c[3:0]
4
d q
d q
clock
reset
clock
clock
clock
q
d
enable
clock
d q
clock
enable
gclk
enable signal must be
glitch free
enable
// 2.resettable latch
always @ (enable or d or reset)
if (reset)
q = 1’b0;
reset
else if (enable)
q = d;
d q
enable
// 2. using a wire
wire y;
assign y = enable ? d : 1’bz;
// 3. using a primitive
bufif1 (y,d,enable);
reset
3’b001
3’b000 count
1
0 3
3
enable
=
3’b101
clock
data_out
data_in
clock
enable
endmodule
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;
// Good commenting
// 8 bit unsigned adder for data signals ‘a’ and ‘b’
// output is sent to UART2
always @ (a or b)
c = a + b;
• 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.
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
// 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;
endmodule
www.vlsiforall.com
Q1. Write a code to generate clk , with and without loop.
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
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
clk=1
clk=0
www.vlsiforall.com
clk=1
./dump.vcd
VLSI FOR ALL
[2023-07-24 12:55:51 UTC] Opening EPWave...
Output:-
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;
begin
$dumpfile("dump.vcd");
$dumpvars;
#100
$finish;
end
endmodule
Output wave:
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
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:-
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
www.vlsiforall.com
endmodule
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
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
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;
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);
www.vlsiforall.com
and (y[2],temp1,en);
and (y[1],temp2,en); VLSI FOR ALL
and (y[0],temp3,en);
endmodule
Structural Modelling
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.
Hardware Design
Simulation
Synthesis
Verification
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.
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:
end
Endmodule
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.
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.
while structural and dataflow modeling are used for implementing the circuit at a
lower level of abstraction, preparing it for synthesis and hardware realization.
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 :
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:
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.
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.
#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.
EX:
`timescale 1ns/100ps // Set time unit to 1 nanosecond and time precision to 100 picoseconds
Delay Statements:
Delay statements are commonly used in testbenches to control the sequence of events and
simulation time.
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 transport delay is a special type of delay represented by #0 and indicates zero delay.
Que 8) How does Verilog handle signal assignments and concurrent statements?
Continuous Assignments:
They are represented using assign statements and describe the direct connections between
input and output signals.
Ex:
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.
a sensitivity list is a crucial component used to specify the events that trigger the execution
of procedural blocks (such as always and initial )
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
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
Event Triggering:
The sensitivity list defines the events that trigger the execution of procedural blocks.
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.
Handling race conditions in Verilog designs is crucial to ensure correct and predictable
behavior during simulation and hardware implementation.
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.
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 for flip-flops to ensure that the reset signal is only applied during a
clock edge.
Ex:
if (reset) begin
// Reset logic
// Normal operation
end
end
Ex:
always @ (a or b) begin
c = a & b;
d = ~a;
end
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.
Functional Verification:
A testbench allows designers to verify the functional correctness of their digital design.
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
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.
In Verilog, you can instantiate modules to create hierarchical designs and connect different
modules together to build complex digital circuits
Ex:
assign Y = A & B;
endmodule
………………….
To instantiate MyModule and connect it to other signals within your design, you use the
following syntax:
Endmodule
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:
Syntax:
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 topmodule;
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.
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.
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;
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).
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.
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.
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.
Port Connectivity:
Module instantiation allows you to connect the ports of lower-level modules to signals
within the higher-level module.
Sequential logic operates on clock edges (rising or falling edges) to transfer data between
registers, enabling the creation of memory elements and state machines
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.
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.
q <= d;
endmodule
………….
JK Flip-Flop Representation:
if (j & ~k)
q <= 1'b1;
q <= 1'b0;
endmodule
QUE 19) How do you model combinational logic in Verilog?
Continuous Assignments:
Continuous assignments are used for modeling simple combinational logic with direct
connections between inputs and outputs.
endmodule
Procedural Blocks:
For more complex combinational logic that involves conditionals and arithmetic operations,
you can use procedural blocks inside an always block.
always @* begin
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.
always @* begin
#10; // Delay of 10 time units
end
endmodule
The testbench provides stimulus to the DUT, captures its outputs, and checks whether the
DUT's behavior matches the expected results
Write the Verilog code for the module you want to test. This is the Design Under Test (DUT)
that you want to verify.
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.
In Verilog, you can simulate asynchronous resets by using the initial or always blocks with
sensitivity to the reset signal
You can use an initial block to model an asynchronous reset. An initial block executes once at
the beginning of the simulation.
initial
begin
else
end
endmodule
You can also use an always block with both the clock and reset signals in the sensitivity list to
model an asynchronous reset.
begin
else
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?
@ (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.
module ClockGenerator(
);
parameter CLOCK_PERIOD = 10; // Time period of the clock (in time units)
begin
else
end
endmodule
frequency and duty cycle of the generated clock are defined by the CLOCK_PERIOD and
DUTY_CYCLE parameters.
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.
Syntax:
or gate2(Y, Y, C);
endmodule
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;
always @* begin
end
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;
initial begin
clk = 0;
forever #10 clk = ~clk; // Generates a 50% duty cycle clock with 10 time units period
end
Endmodule
Input Timing:
EX:
module Testbench;
reg input_signal;
initial begin
#20 input_signal = 1;
#30 input_signal = 0;
end
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;
initial begin
input_signal = 1;
$finish;
end
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:
endmodule
Register:
A register in Verilog represents a sequential element that can store and retain data over time.
Registers have state, which means they can store information and hold their value between
clock cycles.
EX:
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.
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.
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.
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.
always @* begin
end
endmodule
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.
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.
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:
Real time is used for time-based simulation control and analysis of the simulation's duration
in real-world terms.
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.
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.
);
if (ENABLE)
end
endmodule
module MyTopModule;
.data_in(input_data),
.data_out(output_data)
);
// ...
Endmodule
Fixed-Point Representation:
This approach allows you to perform basic floating-point operations using integer arithmetic.
module FixedPointArithmetic;
initial begin
// Perform addition
end
endmodule
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
• 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?
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;