Digital VLSI Design: HDL Tools & Concepts
Digital VLSI Design: HDL Tools & Concepts
DESIGN
PROGRAM ELECTIVE-1
Course Code: R5EL3101T
MODULE 3: HDL
Digital IC Design Tools: Software Used
VLSI Design Type Description Software Used
Logic synthesis tools can automatically convert the design to any fabrication technology.
They simply input the RTL description to the logic synthesis tool and create a new gate-level netlist, using the
new fabrication technology.
By describing designs in HDLs, functional verification of the design can be done early in the design cycle.
Since designers work at the RTL level, they can optimize and modify the RTL description until it meets the
desired functionality.
Popularity of Verilog HDL
Verilog HDL is a general-purpose hardware description language that is easy to learn and easy to use. It is similar
in syntax to the C programming language.
Verilog HDL allows different levels of abstraction to be mixed in the same model. Thus, a designer can define a
hardware model in terms of switches, gates, RTL, or behavioral code.
Basic Concepts
Module: Verilog provides the concept of a module.
PC:Verilog HDL: A Guide to Digital Design and Synthesis, 2nd Edition by Samir Palnitkar
Verilog is both a behavioral and a structural language.
Internals of each module can be defined at four levels of abstraction, depending on the needs of the design.
Behavioral or algorithmic level :This is the highest level of abstraction provided by Verilog HDL. A module can be
implemented in terms of the desired design algorithm without concern for the hardware implementation details. Designing at
this level is very similar to C programming.
Dataflow level : At this level the module is designed by specifying the data flow. The designer is aware of how data flows
between hardware registers and how the data is processed in the design.
Gate level : The module is implemented in terms of logic gates and interconnections between these gates. Design at this
level is similar to describing a design in terms of a gate-level logic diagram.
Instances module ripple_adder (X, Y, S, Co);
input [3:0] X, Y;// Two 4-bit inputs
Instantiation allows the creation of hierarchy in Verilog description output [3:0] S;
output Co;
wire w1, w2, w3;
// instantiating 4 1-bit full adders in Verilog
fulladder u1(X[0], Y[0], 1'b0, S[0], w1);
fulladder u2(X[1], Y[1], w1, S[1], w2);
fulladder u3(X[2], Y[2], w2, S[2], w3);
fulladder u4(X[3], Y[3], w3, S[3], Co);
endmodule
4-bit Ripple Carry Adder module full_adder (a,b,cin,sum,carry);
input a, b, cin;
output sum, carry;
wire c,c1,s;
initial begin
result = a + b; // result = -2
end
Real: Real number constants and real register data types are declared with the keyword real.
They can be specified in decimal notation (e.g., 3.14) or in scientific notation (e.g., 3e6, which is 3 X ).
Real numbers cannot have a range declaration, and their default value is 0.
When a real value is assigned to an integer, the real number is rounded off to the nearest integer.
EXAMPLE 1:
wire a; // scalar net variable, default
wire [7:0] bus; // 8-bit bus
wire [31:01 busA, busB, busC; // 3 buses of 32-bit width.
reg clock; // scalar register,
reg [0 : 40] virtual-addr; // vector register, virtual address 41 bits width
EXAMPLE 2:
busA[7] // bit # 7 of vector busA
bus[2:0] // Three least significant bits of vector bus, // using virtual-
addr[0:l] //TWO most significant bits of vector virtual-addr
Arrays: Arrays are allowed in Verilog for reg, integer, and vector register data types. Arrays are not allowed for
real variables.
integer count[0:7]; / / array of 8 count variables module rom_example
(input clk);
reg B[31:0]; //Array of 32 one-bit Boolean register variables reg [4:0] rom [7:0];
reg [4:0] port [0:7] ; //Array of 8port-ids; each port-id is 5 bits
wide initial begin
rom[0] = 5'b00000;
rom[1] = 5'b10110;
Count [5]; // 5th element of array of count variables end
port_id[3]=port_id[2] | port_id[1] always@(clk)
rom[0][1] = rom[1][2];
// The bit 1 of the first word (rom[0]) is
assigned the value of bit 2 of the second
word (rom[1]).
endmodule
Memories: One often needs to model register files, RAMs, and ROMs.
Memories are modeled in Verilog simply as an array of registers.
Each element of the array is known as a word. Each word can be one or more bits.
Symbol Operation
&& Logical AND
! Logical NOT
|| Logical OR
Symbol Operation
Bitwise Operators: Operands operates on Bits
& AND
~ NOT
| OR
^ XOR
~^ XNOR
~& NAND
module logical_example; module logical_ifelse;
reg a, b; reg a, b, c;
reg [3:0] x, y; initial begin
reg result1, result2, result3, result4; a = 1; b = 0; c = 1;
if (a && c)
initial begin $display("Condition (a && c) is TRUE");
a = 1'b0; else
b = 1'b1; $display("Condition (a && c) is FALSE");
result1 = !a; // logical NOT: !0 = 1 if (a || b)
result2 = a && b; // logical AND: 0 && 1 = $display("Condition (a || b) is TRUE");
0 else
result3 = a || b; // logical OR : 0 || 1 = 1 $display("Condition (a || b) is FALSE");
x = 4'b0000; // treated as FALSE if (!b)
y = 4'b1010; // treated as TRUE (non-zero) $display("Condition (!b) is TRUE");
result4 = (x || y); // since x=0, y≠0 => TRUE else
end $display("Condition (!b) is FALSE");
endmodule end
endmodule
module bitwise_example (a,b, and_result, or_result, xor_result,
xnor_result, not_result);
input [3:0] a, b;
output [3:0] and_result, or_result, xor_result, xnor_result,
not_result;
initial begin
a = 4'b1100; // 12 in decimal
b = 4'b1010; // 10 in decimal
end
assign and_result = a & b; // bitwise AND
assign or_result = a | b; // bitwise OR
assign xor_result = a ^ b; // bitwise XOR
assign xnor_result = a ~^ b; // bitwise XNOR Synthesized Hardware for a_vec & b_vec ;
assign not_result = ~a; // bitwise NOT Each a_vec and b_vec are 3 bits each
end
endmodule
Arithmetic Operators: + (add) , - (subtractor) , * (multiply), / (division), % (modulus)
module adder(A,B,Y);
input [2:0] A, B;
output [2:0] Y;
assign Y=A+B;
endmodule
end
endmodule
Relational Operators: The relational operators // unsigned relational ops
assign a_lt_b = (a < b);
supported for synthesis are: >, <, <=, >=
assign a_gt_b = (a > b);
assign a_le_b = (a <= b);
If variables of a reg type or a net type are compared,
assign a_ge_b = (a >= b);
an unsigned relational operator is synthesized. (==, !=) — treats x/z as unknown (can propagate X)
The operators === (case equality) and !== (case inequality) are not supported for synthesis.
Equality operators are modeled similar to arithmetic operators in terms of whether signed or unsigned comparison is to be
made.
= = = and ! = = are case equality / inequality they compare bit patterns including x and z.
In synthesis, = = =/! = = are not synthesizable to simple hardware in the same way; they are mainly for testbenches and
simulation checks.
Here is an example that uses signed numbers. Note that in this case, the operands of the equality operator are of integer type
because values of this type represent signed numbers.
module shift_operator (a, b, result);
Shift operators: Left shift << and Right shift >> input [7:0] a;
and Arithmetic left shift <<< and Arithmetic input signed [7:0] b;
output reg [7:0] result;
right shift >>> initial begin
a = 8'b00110110; // 54 in decimal
The vacated bits are filled with 0. << and <<< b = -8'd6; // signed -6 in decimal (11111010 in 2's complement)
behave the same (just shift left and pad with 0). // Logical left shift (adds zeros on the right)
result = a << 2; // 00110110 << 2 = 11011000 (216=54*)
>> pads with 0s (logical shift). >>> pads with sign
// Logical right shift (adds zeros on the left)
bit (arithmetic shift, keeps the sign of signed result = a >> 2; // 00110110 >> 2 = 00001101 (13=54/ )
numbers).
// Arithmetic left shift (same as logical left shift)
Left shift also means multiplication with ; n being result = b <<< 2; // -6 (11111010) <<< 2 = 11101000
the number of shifts
// Arithmetic right shift (fills with sign bit instead of 0)
result = b >>> 2; // -6 (11111010) >>> 2 = 11111110 (-2)
Right shift also means division with ; n being the end
number of shifts endmodule
Reduction operator: Reduction operators are and (&), nand (~&a), or ( | ), nor (~| ), xor (^), and
xnor (-^).
Reduction operators take only one operand.
Reduction operators perform a bitwise operation on a single vector operand and yield a l-bit result.
Reduction operators work bit by bit from right to left.
Reduction nand, reduction nor, and reduction xnor are computed by inverting the result of the reduction and, reduction or, and
reduction xor, respectively.
X=4’b1010
/A reduction xor or xnor can be used for even or odd parity //generation of a vector.
~X will do bitwise NOT of the bits and the output is not 1 bit: X=4’b1010;
~X=4’b0101
This is because NOT gate is not multi-input bit gate unlike AND, NOR, NAND,
Part Select: In Verilog, part-select is used to pick a subset of bits from a vector Bit select:
module part_select_example (b0, b1, n0, n1, data);
output [15:0] data;
output [7:0] b0, b1; module bit_select_example (data, bit3, bit7);
input [3:0] n0, n1,n2; input [7:0] data;
output bit3, bit7;
initial begin
data = 16'b1101_1010_0110_1111; initial begin
data = 8'b10110110;
// Fixed part-select
b0 = data[7:0]; // lower 8 bits
b1 = data[15:8]; // upper 8 bits
bit3 = data[3];
n0 = data[3:0]; // lowest 4 bits bit7 = data[7];
n1 = data[11:8]; // bits [11:8] end
n2= {data[15], data [2:0]}; endmodule
end
endmodule
Output:
data = 1101101001101111
b0 = 01101111 (lower byte)
b1 = 11011010 (upper byte)
n0 = 1111 (lowest 4 bits)
n1 = 0110 (bits [11:8])
N2=1111
Conditional Expression: <condition>: <expression1>: <expression2>
initial begin
a = 4'd7;
b = 4'd9;
initial begin
a = 4'd5; // 0101
b = 4'd3; // 0011
c = 4'd2; // 0010
end
assign result = a + b & c;
end
endmodule
module mux4to1_gate (
input i0, i1, i2, i3, // Data inputs
input s0, s1, // Select lines
output out); // Output
wire s0n, s1n, y0, y1, y2, y3;
not (s0n, s0);
not (s1n, s1);
and (y0, i0, s0n, s1n);
and (y1, i1, s0, s1n);
and (y2, i2, s0n, s1);
and (y3, i3, s0, s1);
or (out, y0, y1, y2, y3);
endmodule
Fall Delay: The fall delay is associated with a gate output transition to a o from another value
Boolean expression: out=(a.b)+c module testbench ();
reg a, b, c;
module D (out, a, b, c);
wire out;
output out; D d1(out, a, b, c);
input a,b,c; initial
begin
wire e; a= 1’b0;
and # (5) a1 (e, a, b) ; //Delay of 5 on b= 1’b0;
gate a1 C= 1’b0;
#10 a= 1’b1; b= 1’b1; c= 1’b1;
or #(4) o1(out, e, c); //Delay of 4 on gate #l0 B= l’b1; C= 1’b0; #20
01 end
endmodule endmodule
Dataflow Modelling
For small circuits, the gate-level modeling approach works very well because the number of gates is limited and
the designer can instantiate and connect every gate individually.
Thus, designers can design more effectively if they concentrate on implementing the function at a level of
abstraction higher than gate level.
Verilog allows a circuit to be designed in terms of the data flow between registers and how a design processes
data rather than instantiation of individual gates.
Continuous Assignment:
A continuous assignment is the most basic statement in dataflow modeling, used to drive a value onto a net.
A continuous assignment replaces gates in the description of the circuit and describes the circuit at a higher level of
abstraction.
A continuous assignment statement starts with the keyword assign
Continuous assignments have the following characteristics:
1. The LHS of an assignment must always be a scalar or vector net or a concatenation of scalar and vector nets. It cannot
be a scalar or vector register.
2. Continuous assignments are always active. The assignment expression is evaluated as soon as one of the RHS operands
changes and the value is assigned to the LHS net.
Architectural evaluation takes place at an algorithmic level where the designers do not necessarily think in terms
of logic gates or data flow but in terms of the algorithm they wish to implement in hardware.
But still, complex initial blocks with loops/delays are not synthesizable.
always statement:
The always statement starts at time 0 and executes the statements in the always block continuously in a looping fashion.
This statement is used to model a block of activity that is repeated continuously in a digital circuit.
An example is a clock generator module that toggles the clock signal every half cycle.
In real circuits, the clock generator is active from time 0 to as long as the circuit is powered on.
module clock-gen;
reg clock;
initial clock = l1’b0;
always #10 clock = ~clock;
initial #l000 $finish;
endmodule
always statement starts at time 0 and executes the statement clock = -clock every 10 time units.
Notice that the initialization of clock has to be done inside a separate initial statement.
If we put the initialization of clock inside the always block, clock will be initialized every time the always is entered.
Also, the simulation must be halted inside an initial statement. If there is no $stop or $finish statement to halt the simulation,
the clock generator will run forever.
Procedural Assignments:
Procedural assignments update values of reg, integer, or real variables.
The value placed on a variable will remain unchanged until another procedural assignment updates the variable with
a different value.
The left-hand side of a procedural assignment can be one of the following:
A reg, integer, or real register variable or a memory element
A bit select of these variables (e.g., addr[10])
A part select of these variables (e.g., addr[31:16])
A concatenation of any of the above
There are two types of procedural assignment statements: blocking and nonblocking:
1. Blocking
2. Non-blocking
Blocking Procedural Statements:
Blocking assignment statements are executed in the order they are specified in a sequential block.
A blocking assignment will not block execution of statements that follow in a parallel block.
reg x, y, z;
• Statement y = 1 is executed only after x = 0 is executed.
reg r15: 01 reg_a, reg_b;
integer count; • The behavior in a particular block is sequential in a begin-end block if
initial
begin blocking statements are used, because the statements can execute only
x=0; y=1; z = 1; in sequence.
count = 0;
• All statements x = 0 through reg_b = reg_a are executed at time 0.
reg_a = 16’b0;
reg_b = reg_a; • Statement reg_a[2] = 0 at time = 15
#15 reg_a[2] = 1’b1;
• Statement reg_bl15:13] = {x, y, z} at time = 25
#10 reg_b[15:13] = {x, y, z}
count = count + 1; • Statement count = count + 1 at time = 25
end
• Since there is a delay of 15 and 10 in the preceding statements,
count = count + 1 will be executed at time = 25 units
Nonblocking Assignments:
Nonblocking assignments allow scheduling of assignments without blocking execution of the statements that follow in a
sequential block.
A <= operator is used to specify nonblocking assignments.
Note that this operator has the same as a relational operator, less-than-equal-to.
The operator <= is interpreted as a relational operator in an expression and as an assignment operator in the context of a
nonblocking assignment.