Verilog chapter 7
Verilog chapter 7
Chapter 7
Introduction
• 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.
• Verilog provides designers the ability to describe design
functionality in an algorithmic manner.
• The designer describes the behavior of the circuit.
• Thus, Behavioral modeling represents the circuit at a very high
level of abstraction.
• Design at this level resembles C programming more than it
resembles digital circuit design.
• Behavioral Verilog constructs are similar to C language
constructs in many ways.
• Verilog is rich in behavioral constructs that provide the designer
with a great amount of flexibility.
Learning Objectives
• Explain the significance of structured procedures always
and initial in behavioral modeling.
• Define blocking and nonblocking procedural assignments.
• Understand delay-based timing control mechanism in
behavioral modeling.
• Use regular delays, intra-assignment delays, and zero delays.
• Use level-sensitive timing control mechanism in behavioral
modeling.
• Describe event-based timing control mechanism in behavioral
modeling. Use
• Define sequential and parallel blocks.
• Regular event control, named event control, and event OR
control.
• Explain conditional statements using if and else.
• Describe multiway branching, using case, casex, and casez
statements.
• Understand looping statements such as while, for, repeat, and
forever.
• Understand naming of blocks and disabling of named blocks.
• Use behavioral modeling statements in practical examples.
Structured Procedures
• There are two structured procedure statements in Verilog:
always and initial.
• These statements are the two most basic statements in
behavioral modeling.
• All other behavioral statements can appear only inside these
structured procedure statements.
• Verilog is a concurrent programming language unlike the C
programming language, which is sequential in nature.
• Activity flows in Verilog run in parallel rather than in
sequence.
• Each always and initial statement represents a separate activity
flow in Verilog.
• Each activity flow starts at simulation time 0. The statements
always and initial cannot be nested.
Initial Statement
• All statements inside an initial statement constitute an initial
block. An initial block starts at time 0, executes exactly once
during a simulation, and then does not execute again.
• If there are multiple initial blocks, each block starts to execute
concurrently at time 0.
• Each block finishes execution independently of other blocks.
• Multiple behavioral statements must be grouped, typically
using the keywords begin and end.
• If there is only one behavioral statement, grouping is not
necessary.
Example : initial Statement
module stimulus;
reg x,y, a,b, m;
initial
m = 1'b0; //single statement; does not need to be grouped
initial
begin
#5 a = 1'b1; //multiple statements; need to be grouped
#25 b = 1'b0;
end
initial
begin
#10 x = 1'b0;
#25 y = 1'b1;
end
initial
#50 $finish;
endmodule
• reg x, y, z;
• reg [15:0] reg_a, reg_b;
• integer count;
• //All behavioral statements must be inside an initial or
always block
• initial
• begin
• x = 0; y = 1; z = 1; //Scalar assignments
• count = 0; //Assignment to integer variables
• reg_a = 16'b0; reg_b = reg_a; //Initialize vectors
• reg_a[2] <= #15 1'b1; //Bit select assignment with delay
• reg_b[15:13] <= #10 {x, y, z}; //Assign result of
concatenation
• //to part select of a vector
• count <= count + 1; //Assignment to an integer
(increment)
• end
• In this example, the statements x = 0 through reg_b = reg_a are
executed sequentially at time 0.
• Then the three nonblocking assignments are processed at the same
simulation time.
1. reg_a[2] = 0 is scheduled to execute after 15 units (i.e., time = 15)
2. reg_b[15:13] = {x, y, z} is scheduled to execute after 10 time units
(i.e., time = 10)
3. count = count + 1 is scheduled to be executed without any delay (i.e.,
time = 0)
• Thus, the simulator schedules a nonblocking assignment statement
to execute and continues to the next statement in the block without
waiting for the nonblocking statement to complete execution.
• Typically, nonblocking assignment statements are executed last in
the time step in which they are scheduled, that is, after all the
blocking assignments in that time step are executed.
Application of nonblocking assignments
• Having described the behavior of nonblocking assignments,
it is important to understand why they are used in digital
design.
• They are used as a method to model several concurrent
data transfers that take place after a common event.
• To understand the read and write operations further, consider
Example 7-8, which is intended to swap the values of registers a
and b at each positive edge of clock, using two concurrent always
blocks.
//define parameters
parameter latency = 20;
parameter delta = 2;
//define register variables
reg x, y, z, p, q;
initial
begin
x = 0; // no delay control
#10 y = 1; // delay control with a number. Delay execution of
// y = 1 by 10 units
#latency z = 0; // Delay control with identifier. Delay of 20 units
#(latency + delta) p = 1; // Delay control with expression
#y x = x + 1; // Delay control with identifier. Take value of
y.
#(4:5:6) q = 0; // Minimum, typical and maximum delay values.
//Discussed in gate-level modeling chapter.
end
always
wait (count_enable) #20 count = count + 1;
• In the above example, the value of count_enable is monitored
continuously.
• If count_enable is 0, the statement is not entered. If it is
logical 1, the statement count =count + 1 is executed after 20
time units.
• If count_enable stays at 1, count will be incremented every 20
time units.
Conditional Statements
else if(alu_control == 1)
y = x - z;
else if(alu_control == 2)
y = x * z;
else
$display("Invalid ALU control signal");
Multiway Branching
• In type 3 conditional statement Conditional Statements, there
were many alternatives, from which one was chosen.
• The nested if-else-if can become unwieldy if there are too
many alternatives.
• A shortcut to achieve the same result is to use the case
statement.
Case Statement
The keywords case, endcase, and default are used in the case
statement.
case (expression)
alternative1: statement1;
alternative2: statement2;
alternative3: statement3;
...
...
default: default_statement;
endcase
• Each of statement1, statement2 , default_statement can be a
single statement or a block of multiple statements.
• A block of multiple statements must be grouped by keywords
begin and end.
• The expression is compared to the alternatives in the order
they are written.
• For the first alternative that matches, the corresponding
statement or block is executed. If none of the alternatives
matches, the default_statement is executed.
• The default_statement is optional. Placing of multiple default
statements in one case statement is not allowed. The case
statements can be nested..
4-to-1 Multiplexer with Case Statement
module mux4_to_1 (out, i0, i1, i2, i3, s1, s0);
// Port declarations from the I/O diagram
output out;
input i0, i1, i2, i3;
input s1, s0;
reg out;
always @(s1 or s0 or i0 or i1 or i2 or i3)
case ({s1, s0}) //Switch based on concatenation of control signals
2'd0 : out = i0;
2'd1 : out = i1;
2'd2 : out = i2;
2'd3 : out = i3;
default: $display("Invalid control signals");
endcase
endmodule
Casex, Casez Keywords
integer count;
initial
for ( count=0; count < 128; count = count + 1)
$display("Count = %d", count);
Repeat Loop
• The keyword repeat is used for this loop. The repeat construct
executes the loop a fixed number of times.
• A repeat construct cannot be used to loop on a general logical
expression.
• A while loop is used for that purpose.
• A repeat construct must contain a number, which can be a
constant, a variable or a signal value.
• However, if the number is a variable or signal value, it is
evaluated only when the loop starts and not during the loop
execution.
//Illustration 1: increment and display count from 0 to 127
• integer count;
• initial
• begin
• count = 0;
• repeat(128)
• begin
• $display("Count = %d", count);
• count = count + 1;
• end
• end
//Illustration 2: Data buffer module example
• //After it receives a data_start signal.
• //Reads data for the next 8 cycles.
It shows how to model a data buffer that latches data at the positive edge of
the clock for the next eight cycles after it receives a data start signal.
module data_buffer(data_start, data, clock);
parameter cycles = 8;
input data_start;
input [15:0] data;
input clock;
initial
begin
clock = 1'b0;
forever #10 clock = ~clock; //Clock with period of 20 units
end
Blocks
• Block statements are used to group multiple statements to act together as
one.
• In previous examples, we used keywords begin and end to group multiple
statements. Thus, we used sequential blocks where the statements in the
block execute one after another.
The keywords begin and end are used to group statements into
sequential blocks.
Sequential blocks have the following characteristics:
• The statements in a sequential block are processed in the order
they are specified.
• A statement is executed only after its preceding statement
completes execution (except for nonblocking assignments with
intra-assignment timing control).
• If delay or event control is specified, it is relative to the
simulation time when the previous statement in the block
completed execution
Examples of Sequential Blocks
Sequential block without delay Sequential blocks with delay.
reg x, y; reg x, y;
reg [1:0] z, w; reg [1:0] z, w;
initial initial
begin begin
x = 1'b0; x = 1'b0; //completes at sim. time 0
y = 1'b1; #5 y = 1'b1; //completes at sim. time 5
z = {x, y}; #10 z = {x, y}; //completes at sim.
time 15
w = {y, x};
#20 w = {y, x}; //completes at sim.
end time 35
end
Parallel blocks
initial
fork
x = 1'b0; //completes at simulation time 0
#5 y = 1'b1; //completes at simulation time 5
#10 z = {x, y}; //completes at simulation time 10
#20 w = {y, x}; //completes at simulation time 20
join
Parallel blocks with deliberate race condition
If two statements that affect the same variable complete at the
same time in parallel blocks then implicit race conditions
might arise as shown in the example
//Parallel blocks with deliberate race condition
reg x, y;
reg [1:0] z, w;
initial
fork
x = 1'b0;
y = 1'b1;
z = {x, y};
w = {y, x};
join
All statements start at simulation time 0. The order in which the
statements will execute is not known. So two cases are possible.
Case 1:
Variables z and w will get values 1 and 2 if x = 1'b0 and y = 1'b1
execute first.
Case 2:
Variables z and w will get values 2'bxx and 2'bxx if x = 1'b0 and
y = 1'b1 execute last.
• Variable declarations
• Modules
• User defined primitives, Gate primitives
• Continuous assignments
• initial and always blocks
Bit-wise xor of Two N-bit Buses
// This module generates a bit-wise xor of two N-bit buses
module bitwise_xor (out, i0, i1);
// Parameter Declaration. This can be redefined
parameter N = 32; // 32-bit bus by default
output [N-1:0] out; // Port declarations
input [N-1:0] i0, i1;
// Declare a temporary loop variable. This variable is used only
in //the evaluation of generate blocks. This variable does not
exist //during the simulation of a Verilog design genvar j;
generate for (j=0; j<N; j=j+1) begin: xor_loop //Generate the bit-
//wise xor with a single loop
xor g1 (out[j], i0[j], i1[j]);
end //end of the for loop inside the generate block
endgenerate //end of the generate block
// As an alternate style,
// the xor gates could be replaced by always blocks.
// reg [N-1:0] out;
//generate for (j=0; j<N; j=j+1) begin: bit
// always @(i0[j] or i1[j]) out[j] = i0[j] ^ i1[j];
//end
//endgenerate
endmodule
• Modules
• User defined primitives, Gate primitives
• Continuous assignments
• initial and always blocks
Generate Case
• Modules
• User defined primitives, Gate primitives
• Continuous assignments
• initial and always blocks
• Example 7-32 Generated Ripple Adder
• // This module generates a gate level ripple adder
• module ripple_adder(co, sum, a0, a1, ci);
• // Parameter Declaration. This can be redefined
• parameter N = 4; // 4-bit bus by default
• // Port declarations
• output [N-1:0] sum;
• output co;
• input [N-1:0] a0, a1;
• input ci;
• //Local wire declaration
• wire [N-1:0] carry;
• //Assign 0th bit of carry equal to carry input
• assign carry[0] = ci;
• // Declare a temporary loop variable. This variable is used only
• // in the evaluation of generate blocks. This variable does not
• // exist during the simulation of a Verilog design because the
• // generate loops are unrolled before simulation.
• genvar i;
• //Generate the bit-wise Xor with a single loop
• generate for (i=0; i<N; i=i+1) begin: r_loop
• wire t1, t2, t3;
• xor g1 (t1, a0[i], a1[i]);
• xor g2 (sum[i], t1, carry[i]);
• and g3 (t2, a0[i], a1[i]);
• and g4 (t3, t1, carry[i]);
• or g5 (carry[i+1], t2, t3);
• end //end of the for loop inside the generate block
• endgenerate //end of the generate block
• // For the above generate loop, the following relative
hierarchical
• // instance names are generated
• // xor : r_loop[0].g1, r_loop[1].g1, r_loop[2].g1,
r_loop[3].g1
• r_loop[0].g2, r_loop[1].g2, r_loop[2].g2, r_loop[3].g2
• // and : r_loop[0].g3, r_loop[1].g3, r_loop[2].g3,
r_loop[3].g3
• r_loop[0].g4, r_loop[1].g4, r_loop[2].g4, r_loop[3].g4
• // or : r_loop[0].g5, r_loop[1].g5, r_loop[2].g5,
r_loop[3].g5
• // Generated instances are connected with the following
• // generated nets
• // Nets: r_loop[0].t1, r_loop[0].t2, r_loop[0].t3
• // r_loop[1].t1, r_loop[1].t2, r_loop[1].t3
• // r_loop[2].t1, r_loop[2].t2, r_loop[2].t3
• // r_loop[3].t1, r_loop[3].t2, r_loop[3].t3
• assign co = carry[N];
• endmodule